Initial commit

This commit is contained in:
Nathan Adams
2013-07-20 17:41:56 -05:00
commit 3b1e713fc4
606 changed files with 136001 additions and 0 deletions

View File

@@ -0,0 +1,649 @@
<?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 ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
Pluf::loadFunction('Pluf_Shortcuts_RenderToResponse');
Pluf::loadFunction('Pluf_Shortcuts_GetObjectOr404');
Pluf::loadFunction('Pluf_Shortcuts_GetFormForModel');
/**
* Administration's views.
*/
class IDF_Views_Admin
{
/**
* Start page of the administration.
*/
public $forge_precond = array('Pluf_Precondition::staffRequired');
public function forge($request, $match)
{
$title = __('Forge Management');
$forge = IDF_Forge::instance();
if ($request->method == 'POST') {
$form = new IDF_Form_Admin_ForgeConf($request->POST);
if ($form->isValid()) {
$forge->setCustomForgePageEnabled($form->cleaned_data['enabled']);
$forge->setCustomForgePageContent($form->cleaned_data['content']);
$request->user->setMessage(__('The forge configuration has been saved.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::forge');
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$params = array();
$params['enabled'] = $forge->isCustomForgePageEnabled();
if (($content = $forge->getCustomForgePageContent(false)) !== false) {
$params['content'] = $content;
}
if (count($params) == 0) {
$params = null; //Nothing in the db, so new form.
}
$form = new IDF_Form_Admin_ForgeConf($params);
}
return Pluf_Shortcuts_RenderToResponse('idf/gadmin/forge/index.html',
array(
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* Projects overview.
*
*/
public $projects_precond = array('Pluf_Precondition::staffRequired');
public function projects($request, $match)
{
$title = __('Projects');
$pag = new Pluf_Paginator(new IDF_Project());
$pag->class = 'recent-issues';
$pag->summary = __('This table shows the projects in the forge.');
$pag->action = 'IDF_Views_Admin::projects';
$pag->edit_action = array('IDF_Views_Admin::projectUpdate', 'id');
$pag->sort_order = array('shortname', 'ASC');
$list_display = array(
'shortname' => __('Short Name'),
'name' => __('Name'),
array('id', 'IDF_Views_Admin_projectSize', __('Repository Size')),
);
$pag->configure($list_display, array(),
array('shortname' ));
$pag->extra_classes = array('', '', 'right');
$pag->items_per_page = 25;
$pag->no_results_text = __('No projects were found.');
$pag->setFromRequest($request);
return Pluf_Shortcuts_RenderToResponse('idf/gadmin/projects/index.html',
array(
'page_title' => $title,
'projects' => $pag,
'size' => IDF_Views_Admin_getForgeSize(),
),
$request);
}
/**
* Administrate the labels of a project.
*/
public $projectLabels_precond = array('Pluf_Precondition::staffRequired');
public function projectLabels($request, $match)
{
$title = __('Project Labels');
$forge = IDF_Forge::instance();
if ($request->method == 'POST') {
$form = new IDF_Form_Admin_LabelConf($request->POST);
if ($form->isValid()) {
$forge->setProjectLabels($form->cleaned_data['project_labels']);
$request->user->setMessage(__('The label configuration has been saved.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::projectLabels');
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$params = array();
if (($labels = $forge->getProjectLabels(false)) !== false) {
$params['project_labels'] = $labels;
}
if (count($params) == 0) {
$params = null; //Nothing in the db, so new form.
}
$form = new IDF_Form_Admin_LabelConf($params);
}
return Pluf_Shortcuts_RenderToResponse('idf/gadmin/projects/labels.html',
array(
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* Edition of a project.
*
* One cannot switch from one source backend to another.
*/
public $projectUpdate_precond = array('Pluf_Precondition::staffRequired');
public function projectUpdate($request, $match)
{
$project = Pluf_Shortcuts_GetObjectOr404('IDF_Project', $match[1]);
$title = sprintf(__('Update %s'), $project->name);
$params = array(
'project' => $project,
);
if ($request->method == 'POST') {
$form = new IDF_Form_Admin_ProjectUpdate($request->POST, $params);
if ($form->isValid()) {
$form->save();
$request->user->setMessage(__('The project has been updated.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::projectUpdate',
array($project->id));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_Admin_ProjectUpdate(null, $params);
}
$arrays = IDF_Views_Project::autoCompleteArrays();
return Pluf_Shortcuts_RenderToResponse('idf/gadmin/projects/update.html',
array_merge(
array(
'page_title' => $title,
'project' => $project,
'form' => $form,
),
$arrays
),
$request);
}
/**
* Creation of a project.
*
* A project can use another project as template. In that case,
* everything but the data in the input at creation time is
* reused, including the wiki pages.
*/
public $projectCreate_precond = array('Pluf_Precondition::staffRequired');
public function projectCreate($request, $match)
{
$title = __('Create Project');
$extra = array('user' => $request->user);
if ($request->method == 'POST') {
$form = new IDF_Form_Admin_ProjectCreate($request->POST, $extra);
if ($form->isValid()) {
$project = $form->save();
$request->user->setMessage(__('The project has been created.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::projects');
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_Admin_ProjectCreate(null, $extra);
}
$base = Pluf::f('url_base').Pluf::f('idf_base').'/p/';
$arrays = IDF_Views_Project::autoCompleteArrays();
return Pluf_Shortcuts_RenderToResponse('idf/gadmin/projects/create.html',
array_merge(
array(
'page_title' => $title,
'form' => $form,
'base_url' => $base,
),
$arrays
),
$request);
}
/**
* Deletion of a project.
*
* Only the forge administrator can perform this operation.
*/
public $projectDelete_precond = array('Pluf_Precondition::adminRequired');
public function projectDelete($request, $match)
{
$project = Pluf_Shortcuts_GetObjectOr404('IDF_Project', $match[1]);
$title = sprintf(__('Delete %s Project'), $project);
$extra = array('project' => $project,
'user' => $request->user);
if ($request->method == 'POST') {
$form = new IDF_Form_Admin_ProjectDelete($request->POST, $extra);
if ($form->isValid()) {
$project = $form->save();
$request->user->setMessage(__('The project has been deleted.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::projects');
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_Admin_ProjectDelete(null, $extra);
}
return Pluf_Shortcuts_RenderToResponse('idf/gadmin/projects/delete.html',
array(
'project' => $project,
'page_title' => $title,
'form' => $form,
'stats' => $project->getStats(),
'code' => $form->getCode(),
),
$request);
}
/**
* Users overview.
*
*/
public $users_precond = array('Pluf_Precondition::staffRequired');
public function users($request, $match, $not_validated=false)
{
$pag = new Pluf_Paginator(new Pluf_User());
$db =& Pluf::db();
$true = Pluf_DB_BooleanToDb(true, $db);
if ($not_validated) {
$pag->forced_where = new Pluf_SQL('first_name = \'---\' AND active!='.$true);
$title = __('Not Validated User List');
$pag->action = 'IDF_Views_Admin::usersNotValidated';
} else {
$pag->forced_where = new Pluf_SQL('first_name != \'---\'');
$title = __('User List');
$pag->action = 'IDF_Views_Admin::users';
}
$pag->class = 'recent-issues';
$pag->summary = __('This table shows the users in the forge.');
$pag->edit_action = array('IDF_Views_Admin::userUpdate', 'id');
$pag->sort_order = array('login', 'ASC');
$list_display = array(
'login' => __('login'),
array('last_name', 'Pluf_Paginator_ToString', __('Name')),
array('staff', 'IDF_Views_Admin_bool', __('Staff')),
array('administrator', 'IDF_Views_Admin_bool', __('Admin')),
array('active', 'IDF_Views_Admin_bool', __('Active')),
array('last_login', 'Pluf_Paginator_DateYMDHM', __('Last Login')),
);
$pag->extra_classes = array('', '', 'a-c', 'a-c', 'a-c', 'a-c');
$pag->configure($list_display,
array('login', 'last_name', 'email'),
array('login', 'last_login'));
$pag->items_per_page = 50;
$pag->no_results_text = __('No users were found.');
$pag->setFromRequest($request);
return Pluf_Shortcuts_RenderToResponse('idf/gadmin/users/index.html',
array(
'page_title' => $title,
'users' => $pag,
'not_validated' => $not_validated,
),
$request);
}
/**
* Not validated users.
*/
public $usersNotValidated_precond = array('Pluf_Precondition::staffRequired');
public function usersNotValidated($request, $match)
{
return $this->users($request, $match, true);
}
/**
* Edition of a user.
*
* Staff cannot edit other staff people and only admin can edit
* staff.
*/
public $userUpdate_precond = array('Pluf_Precondition::staffRequired');
public function userUpdate($request, $match)
{
$user = Pluf_Shortcuts_GetObjectOr404('Pluf_User', $match[1]);
$title = sprintf(__('Update %s'), $user->__toString());
$params = array(
'user' => $user,
'request' => $request,
);
// Check the rights.
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::users');
$error = __('You do not have the rights to update this user.');
if ($user->administrator and $request->user->id != $user->id) {
$request->user->setMessage($error);
return new Pluf_HTTP_Response_Redirect($url);
}
if ($user->staff) {
if (!$request->user->administrator and $request->user->id != $user->id) {
$request->user->setMessage($error);
return new Pluf_HTTP_Response_Redirect($url);
}
}
if ($request->method == 'POST') {
$form = new IDF_Form_Admin_UserUpdate(array_merge($request->POST,
$request->FILES),
$params);
if ($form->isValid()) {
$form->save();
$request->user->setMessage(__('The user has been updated.'));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_Admin_UserUpdate(null, $params);
}
return Pluf_Shortcuts_RenderToResponse('idf/gadmin/users/update.html',
array(
'page_title' => $title,
'cuser' => $user,
'form' => $form,
),
$request);
}
/**
* Create a new user.
*
* Only staff can add a user. The user can be added together with
* a public ssh key.
*/
public $userCreate_precond = array('Pluf_Precondition::staffRequired');
public function userCreate($request, $match)
{
$params = array(
'request' => $request,
);
if ($request->method == 'POST') {
$form = new IDF_Form_Admin_UserCreate(array_merge($request->POST,
$request->FILES),
$params);
if ($form->isValid()) {
$cuser = $form->save();
$request->user->setMessage(sprintf(__('The user %s has been created.'), (string) $cuser));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::users');
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_Admin_UserCreate(null, $params);
}
$title = __('Add User');
return Pluf_Shortcuts_RenderToResponse('idf/gadmin/users/create.html',
array(
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* Usher servers overview
*
*/
public $usher_precond = array('Pluf_Precondition::staffRequired');
public function usher($request, $match)
{
$title = __('Usher management');
$servers = array();
foreach (IDF_Scm_Monotone_Usher::getServerList() as $server) {
$servers[] = (object)array(
"name" => $server,
"status" => IDF_Scm_Monotone_Usher::getStatus($server),
);
}
return Pluf_Shortcuts_RenderToResponse(
'idf/gadmin/usher/index.html',
array(
'page_title' => $title,
'servers' => $servers,
),
$request
);
}
/**
* Usher control
*
*/
public $usherControl_precond = array('Pluf_Precondition::staffRequired');
public function usherControl($request, $match)
{
$title = __('Usher control');
$action = $match[1];
if (!empty($action)) {
if (!in_array($action, array('reload', 'shutdown', 'startup'))) {
throw new Pluf_HTTP_Error404();
}
$msg = null;
if ($action == 'reload') {
IDF_Scm_Monotone_Usher::reload();
$msg = __('Usher configuration has been reloaded');
}
else if ($action == 'shutdown') {
IDF_Scm_Monotone_Usher::shutDown();
$msg = __('Usher has been shut down');
}
else
{
IDF_Scm_Monotone_Usher::startUp();
$msg = __('Usher has been started up');
}
$request->user->setMessage($msg);
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::usherControl', array(''));
return new Pluf_HTTP_Response_Redirect($url);
}
return Pluf_Shortcuts_RenderToResponse(
'idf/gadmin/usher/control.html',
array(
'page_title' => $title,
'status' => IDF_Scm_Monotone_Usher::getStatus(),
),
$request
);
}
/**
* Usher control
*
*/
public $usherServerControl_precond = array('Pluf_Precondition::staffRequired');
public function usherServerControl($request, $match)
{
$server = $match[1];
if (!in_array($server, IDF_Scm_Monotone_Usher::getServerList())) {
throw new Pluf_HTTP_Error404();
}
$action = $match[2];
if (!in_array($action, array('start', 'stop', 'kill'))) {
throw new Pluf_HTTP_Error404();
}
$msg = null;
if ($action == 'start') {
IDF_Scm_Monotone_Usher::startServer($server);
$msg = sprintf(__('The server "%s" has been started'), $server);
}
else if ($action == 'stop') {
IDF_Scm_Monotone_Usher::stopServer($server);
$msg = sprintf(__('The server "%s" has been stopped'), $server);
}
else
{
IDF_Scm_Monotone_Usher::killServer($server);
$msg = sprintf(__('The server "%s" has been killed'), $server);
}
$request->user->setMessage($msg);
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::usher');
return new Pluf_HTTP_Response_Redirect($url);
}
/**
* Open connections for a configured server
*
*/
public $usherServerConnections_precond = array('Pluf_Precondition::staffRequired');
public function usherServerConnections($request, $match)
{
$server = $match[1];
if (!in_array($server, IDF_Scm_Monotone_Usher::getServerList())) {
throw new Pluf_HTTP_Error404();
}
$title = sprintf(__('Open connections for "%s"'), $server);
$connections = IDF_Scm_Monotone_Usher::getConnectionList($server);
if (count($connections) == 0) {
$request->user->setMessage(sprintf(
__('no connections for server "%s"'), $server
));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::usher');
return new Pluf_HTTP_Response_Redirect($url);
}
return Pluf_Shortcuts_RenderToResponse(
'idf/gadmin/usher/connections.html',
array(
'page_title' => $title,
'server' => $server,
'connections' => $connections,
),
$request
);
}
}
function IDF_Views_Admin_bool($field, $item)
{
$img = ($item->$field) ? 'day' : 'night';
$text = ($item->$field) ? __('Yes') : __('No');
return sprintf('<img src="'.Pluf::f('url_media').'/idf/img/%s.png" alt="%s" /> ', $img, $text);
}
/**
* Display the size of the project.
*
* @param string Field
* @param IDF_Project
* @return string
*/
function IDF_Views_Admin_projectSize($field, $project)
{
$size = $project->getRepositorySize();
if ($size == -1) {
return '';
}
return Pluf_Utils::prettySize($size);
}
/**
* Get a forge size.
*
* @return array Associative array with the size of each element
*/
function IDF_Views_Admin_getForgeSize($force=false)
{
$conf = new IDF_Gconf();
$conf->setModel((object) array('_model'=>'IDF_Forge', 'id'=> 1));
$res = array();
$res['repositories'] = 0;
foreach (Pluf::factory('IDF_Project')->getList() as $prj) {
$size = $prj->getRepositorySize($force);
if ($size != -1) {
$res['repositories'] += $size;
}
}
$last_eval = $conf->getVal('downloads_size_check_date', 0);
if (Pluf::f('idf_no_size_check', false) or
(!$force and $last_eval > time()-172800)) {
$res['downloads'] = $conf->getVal('downloads_size', 0);
} else {
$conf->setVal('downloads_size_check_date', time());
$cmd = Pluf::f('idf_exec_cmd_prefix', '').'du -sk '
.escapeshellarg(Pluf::f('upload_path'));
$out = explode(' ', shell_exec($cmd), 2);
$res['downloads'] = $out[0]*1024;
$conf->setVal('downloads_size', $res['downloads']);
}
$last_eval = $conf->getVal('attachments_size_check_date', 0);
if (Pluf::f('idf_no_size_check', false) or
(!$force and $last_eval > time()-172800)) {
$res['attachments'] = $conf->getVal('attachments_size', 0);
} else {
$conf->setVal('attachments_size_check_date', time());
$cmd = Pluf::f('idf_exec_cmd_prefix', '').'du -sk '
.escapeshellarg(Pluf::f('upload_path'));
$out = explode(' ', shell_exec($cmd), 2);
$res['attachments'] = $out[0]*1024;
$conf->setVal('attachments_size', $res['attachments']);
}
$last_eval = $conf->getVal('database_size_check_date', 0);
if (Pluf::f('idf_no_size_check', false) or
(!$force and $last_eval > time()-172800)) {
$res['database'] = $conf->getVal('database_size', 0);
} else {
$conf->setVal('database_size_check_date', time());
$res['database'] = IDF_Views_Admin_getForgeDbSize();
$conf->setVal('database_size', $res['database']);
}
$res['total'] = $res['repositories'] + $res['downloads'] + $res['attachments'] + $res['database'];
return $res;
}
/**
* Get the database size as given by the database.
*
* @return int Database size
*/
function IDF_Views_Admin_getForgeDbSize()
{
$db = Pluf::db();
if (Pluf::f('db_engine') == 'SQLite') {
return filesize(Pluf::f('db_database'));
}
switch (Pluf::f('db_engine')) {
case 'PostgreSQL':
$sql = 'SELECT relname, pg_total_relation_size(CAST(relname AS
TEXT)) AS size FROM pg_class AS pgc, pg_namespace AS pgn
WHERE pg_table_is_visible(pgc.oid) IS TRUE AND relkind = \'r\'
AND pgc.relnamespace = pgn.oid
AND pgn.nspname NOT IN (\'information_schema\', \'pg_catalog\')';
break;
case 'MySQL':
default:
$sql = 'SHOW TABLE STATUS FROM `'.Pluf::f('db_database').'`';
break;
}
$rs = $db->select($sql);
$total = 0;
switch (Pluf::f('db_engine')) {
case 'PostgreSQL':
foreach ($rs as $table) {
$total += $table['size'];
}
break;
case 'MySQL':
default:
foreach ($rs as $table) {
$total += $table['Data_length'] + $table['Index_length'];
}
break;
}
return $total;
}

View File

@@ -0,0 +1,131 @@
<?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 ***** */
/**
* API views.
*
* These are just small wrappers around the "normal" views. The normal
* views are called with a third parameters $api set to true to return
* JSON instead of HTML.
*
* A special precondition is used to set the $request->user from the
* _login, _hash and _salt parameters.
*/
class IDF_Views_Api
{
/**
* View list of issues for a given project.
*/
public $issuesIndex_precond = array('IDF_Precondition::apiSetUser',
'IDF_Precondition::accessIssues');
public function issuesIndex($request, $match)
{
$views = new IDF_Views_Issue();
$p = $views->index($request, $match, true);
$out = array(
'project' => $request->project->shortname,
'open' => $p['open'],
'closed' => $p['closed'],
'issues' => $p['issues']->render_array(),
);
return new Pluf_HTTP_Response_Json($out);
}
/**
* Create a new issue.
*/
public $issueCreate_precond = array('IDF_Precondition::apiSetUser',
'Pluf_Precondition::loginRequired',
'IDF_Precondition::accessIssues');
public function issueCreate($request, $match)
{
$views = new IDF_Views_Issue();
$p = $views->create($request, $match, true);
$out = array();
if ($request->method == 'GET') {
// We give the details of the form
$out['help'] = 'A POST request against this url will allow you to create a new issue.';
if ($request->user->hasPerm('IDF.project-owner', $request->project)
or $request->user->hasPerm('IDF.project-member', $request->project)) {
$out['status'] = array();
foreach (self::getTags($request->project) as $tag) {
$out['status'][] = $tag->name;
}
}
} else {
// We need to give back the results of the creation
if (is_object($p) and 'IDF_Issue' == get_class($p)) {
$out['message'] = 'success';
$out['issue'] = $p->id;
} else {
$out['message'] = 'error';
$out['errors'] = $p['form']->errors;
}
}
return new Pluf_HTTP_Response_Json($out);
}
/**
* List all the projects
*/
public $projectIndex_precond = array('IDF_Precondition::apiSetUser');
public function projectIndex($request, $match)
{
$projects = IDF_Views::getProjects($request->user);
$data = array();
foreach ($projects as $p) {
$data[] = array("shortname" => $p->shortname, "name" => $p->name, "shortdesc" => $p->shortdesc, "private" => $p->private);
}
$out = array();
$out['message'] = 'success';
$out['projects'] = $data;
return new Pluf_HTTP_Response_Json($out);
}
/**
* Get the list of tags to give them to the end users when doing a
* GET request against a form. That way it is possible for them to
* know which tags/labels are available.
*
* @param IDF_Project Current project
* @param string Which tags to get ('issue-open')
* @return ArrayObject Tags
*/
public static function getTags($project, $what='issue-open')
{
switch ($what) {
case 'issue-open':
$key = 'labels_issue_open';
$default = IDF_Form_IssueTrackingConf::init_open;
return $project->getTagsFromConfig($key, $default);
case 'issue-closed':
return $project->getTagIdsByStatus('closed');
}
return array();
}
}

View File

@@ -0,0 +1,425 @@
<?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 ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
Pluf::loadFunction('Pluf_Shortcuts_RenderToResponse');
Pluf::loadFunction('Pluf_Shortcuts_GetObjectOr404');
Pluf::loadFunction('Pluf_Shortcuts_GetFormForModel');
/**
* Download's views.
*
* - List all the files.
* - Upload a file.
* - See the details of a file.
*/
class IDF_Views_Download
{
/**
* List the files available for download.
*/
public $index_precond = array('IDF_Precondition::accessDownloads');
public function index($request, $match)
{
$prj = $request->project;
$title = sprintf(__('%s Downloads'), (string) $prj);
// Paginator to paginate the files to download.
$pag = new Pluf_Paginator(new IDF_Upload());
//$pag->class = 'recent-issues';
$pag->class = 'uploads';
$pag->item_extra_props = array('project_m' => $prj,
'shortname' => $prj->shortname);
$pag->summary = __('This table shows the files to download.');
$pag->action = array('IDF_Views_Download::index', array($prj->shortname));
$pag->edit_action = array('IDF_Views_Download::view', 'shortname', 'id');
$sql = 'project=%s';
$ptags = self::getDownloadTags($prj);
$dtag = array_pop($ptags); // The last tag is the deprecated tag.
$ids = self::getDeprecatedFilesIds($prj);
if (count($ids)) {
$sql .= ' AND id NOT IN ('.implode(',', $ids).')';
}
$pag->forced_where = new Pluf_SQL($sql, array($prj->id));
$list_display = array(
'file' => __('File'),
array('summary', 'IDF_Views_Download_SummaryAndLabels', __('Summary')),
array('filesize', 'IDF_Views_Download_Size', __('Size')),
array('creation_dtime', 'Pluf_Paginator_DateYMD', __('Uploaded')),
array('downloads', 'Pluf_Paginator_DisplayVal', __('Downlaods')),
);
$pag->configure($list_display, array(), array('file', 'filesize', 'creation_dtime'));
$pag->items_per_page = 10;
$pag->no_results_text = __('No downloads were found.');
$pag->sort_order = array('creation_dtime', 'DESC');
$pag->setFromRequest($request);
return Pluf_Shortcuts_RenderToResponse('idf/downloads/index.html',
array(
'page_title' => $title,
'downloads' => $pag,
'deprecated' => count($ids),
'dlabel' => $dtag,
),
$request);
}
/**
* View details of a file.
*/
public $view_precond = array('IDF_Precondition::accessDownloads');
public function view($request, $match)
{
$prj = $request->project;
$upload = Pluf_Shortcuts_GetObjectOr404('IDF_Upload', $match[2]);
$prj->inOr404($upload);
$title = sprintf(__('Download %s'), $upload->summary);
$form = false;
$ptags = self::getDownloadTags($prj);
$dtag = array_pop($ptags); // The last tag is the deprecated tag.
$tags = $upload->get_tags_list();
$deprecated = Pluf_Model_InArray($dtag, $tags);
if ($request->method == 'POST' and
true === IDF_Precondition::projectMemberOrOwner($request)) {
$form = new IDF_Form_UpdateUpload($request->POST,
array('project' => $prj,
'upload' => $upload,
'user' => $request->user));
if ($form->isValid()) {
$upload = $form->save();
$urlfile = Pluf_HTTP_URL_urlForView('IDF_Views_Download::view',
array($prj->shortname, $upload->id));
$request->user->setMessage(sprintf(__('The file <a href="%1$s">%2$s</a> has been updated.'), $urlfile, Pluf_esc($upload->file)));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} elseif (true === IDF_Precondition::projectMemberOrOwner($request)) {
$form = new IDF_Form_UpdateUpload(null,
array('upload' => $upload,
'project' => $prj,
'user' => $request->user));
}
return Pluf_Shortcuts_RenderToResponse('idf/downloads/view.html',
array(
'file' => $upload,
'deprecated' => $deprecated,
'tags' => $tags,
'auto_labels' => self::autoCompleteArrays($prj),
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* Delete a file.
*/
public $delete_precond = array('IDF_Precondition::accessDownloads',
'IDF_Precondition::projectMemberOrOwner');
public function delete($request, $match)
{
$prj = $request->project;
$upload = Pluf_Shortcuts_GetObjectOr404('IDF_Upload', $match[2]);
$prj->inOr404($upload);
$title = sprintf(__('Delete Download %s'), $upload->summary);
$form = false;
$ptags = self::getDownloadTags($prj);
$dtag = array_pop($ptags); // The last tag is the deprecated tag.
$tags = $upload->get_tags_list();
$deprecated = Pluf_Model_InArray($dtag, $tags);
if ($request->method == 'POST') {
$fname = $upload->file;
@unlink(Pluf::f('upload_path').'/'.$prj->shortname.'/files/'.$fname);
/**
* [signal]
*
* IDF_Upload::delete
*
* [sender]
*
* IDF_Form_UpdateUpload
*
* [description]
*
* This signal allows an application to perform a set of tasks
* just before the deletion of the corresponding object in the
* database but just after the deletion from the storage.
*
* [parameters]
*
* array('upload' => $upload);
*
*/
$params = array('upload' => $upload);
Pluf_Signal::send('IDF_Upload::delete',
'IDF_Views_Download', $params);
$upload->delete();
$request->user->setMessage(__('The file has been deleted.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
return Pluf_Shortcuts_RenderToResponse('idf/downloads/delete.html',
array(
'file' => $upload,
'deprecated' => $deprecated,
'tags' => $tags,
'page_title' => $title,
),
$request);
}
/**
* Download the file with the given name.
*/
public $download_precond = array('IDF_Precondition::accessDownloads');
public function download($request, $match)
{
$prj = $request->project;
$sql = new Pluf_SQL('file=%s', array($match[2]));
$upload = Pluf::factory('IDF_Upload')->getOne(array('filter' => $sql->gen()));
if (!$upload) throw new Pluf_HTTP_Error404();
$prj->inOr404($upload);
$upload->downloads += 1;
$upload->update();
$path = $upload->getFullPath();
$mime = IDF_FileUtil::getMimeType($path);
$render = new Pluf_HTTP_Response_File($path, $mime[0]);
$render->headers['Content-MD5'] = $upload->md5;
$render->headers['Content-Disposition'] = 'attachment; filename="'.$upload->file.'"';
return $render;
}
/**
* Download the file with the given ID (for legacy links).
*/
public $downloadById_precond = array('IDF_Precondition::accessDownloads');
public function downloadById($request, $match)
{
$upload = Pluf_Shortcuts_GetObjectOr404('IDF_Upload', $match[2]);
return new Pluf_HTTP_Response_Redirect(
Pluf_HTTP_URL_urlForView('IDF_Views_Download::download', array(
$match[1], $upload->file
)), 301
);
}
/**
* Create a new file for download.
*/
public $create_precond = array('IDF_Precondition::accessDownloads',
'IDF_Precondition::projectMemberOrOwner');
public function create($request, $match)
{
$prj = $request->project;
$title = __('New Download');
if ($request->method == 'POST') {
$form = new IDF_Form_Upload(array_merge($request->POST, $request->FILES),
array('project' => $prj,
'user' => $request->user));
if ($form->isValid()) {
$upload = $form->save();
$urlfile = Pluf_HTTP_URL_urlForView('IDF_Views_Download::view',
array($prj->shortname, $upload->id));
$request->user->setMessage(sprintf(__('The <a href="%s">file</a> has been uploaded.'), $urlfile));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_Upload(null,
array('project' => $prj,
'user' => $request->user));
}
return Pluf_Shortcuts_RenderToResponse('idf/downloads/create.html',
array(
'auto_labels' => self::autoCompleteArrays($prj),
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* Create new downloads from an uploaded archive.
*/
public $createFromArchive_precond = array('IDF_Precondition::accessDownloads',
'IDF_Precondition::projectMemberOrOwner');
public function createFromArchive($request, $match)
{
$prj = $request->project;
$title = __('New Downloads from Archive');
if ($request->method == 'POST') {
$form = new IDF_Form_UploadArchive(array_merge($request->POST, $request->FILES),
array('project' => $prj,
'user' => $request->user));
if ($form->isValid()) {
$upload = $form->save();
$request->user->setMessage(__('The archive has been uploaded and processed.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_UploadArchive(null,
array('project' => $prj,
'user' => $request->user));
}
return Pluf_Shortcuts_RenderToResponse('idf/downloads/createFromArchive.html',
array(
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* Create the autocomplete arrays for the little AJAX stuff.
*/
public static function autoCompleteArrays($project)
{
$conf = new IDF_Conf();
$conf->setProject($project);
$st = preg_split("/\015\012|\015|\012/",
$conf->getVal('labels_download_predefined', IDF_Form_UploadConf::init_predefined), -1, PREG_SPLIT_NO_EMPTY);
$auto = '';
foreach ($st as $s) {
$v = '';
$d = '';
$_s = explode('=', $s, 2);
if (count($_s) > 1) {
$v = trim($_s[0]);
$d = trim($_s[1]);
} else {
$v = trim($_s[0]);
}
$auto .= sprintf('{ name: "%s", to: "%s" }, ',
Pluf_esc($d), Pluf_esc($v));
}
return substr($auto, 0, -2);
}
/**
* View list of downloads with a given label.
*/
public $listLabel_precond = array('IDF_Precondition::accessDownloads');
public function listLabel($request, $match)
{
$prj = $request->project;
$tag = Pluf_Shortcuts_GetObjectOr404('IDF_Tag', $match[2]);
$prj->inOr404($tag);
$title = sprintf(__('%1$s Downloads with Label %2$s'), (string) $prj,
(string) $tag);
// Paginator to paginate the downloads
$ptags = self::getDownloadTags($prj);
$dtag = array_pop($ptags); // The last tag is the deprecated tag.
$pag = new Pluf_Paginator(new IDF_Upload());
$pag->model_view = 'join_tags';
$pag->class = 'recent-issues';
$pag->item_extra_props = array('project_m' => $prj,
'shortname' => $prj->shortname);
$pag->summary = sprintf(__('This table shows the downloads with label %s.'), (string) $tag);
$pag->forced_where = new Pluf_SQL('project=%s AND idf_tag_id=%s', array($prj->id, $tag->id));
$pag->action = array('IDF_Views_Download::listLabel', array($prj->shortname, $tag->id));
$pag->edit_action = array('IDF_Views_Download::view', 'shortname', 'id');
$list_display = array(
'file' => __('File'),
array('summary', 'IDF_Views_Download_SummaryAndLabels', __('Summary')),
array('filesize', 'IDF_Views_Download_Size', __('Size')),
array('creation_dtime', 'Pluf_Paginator_DateYMD', __('Uploaded')),
);
$pag->configure($list_display, array(), array('file', 'filesize', 'creation_dtime'));
$pag->items_per_page = 10;
$pag->no_results_text = __('No downloads were found.');
$pag->sort_order = array('creation_dtime', 'DESC');
$pag->setFromRequest($request);
return Pluf_Shortcuts_RenderToResponse('idf/downloads/index.html',
array(
'page_title' => $title,
'label' => $tag,
'downloads' => $pag,
'dlabel' => $dtag,
),
$request);
}
/**
* Get the download tags.
*
* @param IDF_Project
* @return ArrayObject The tags
*/
public static function getDownloadTags($project)
{
return $project->getTagsFromConfig('labels_download_predefined',
IDF_Form_UploadConf::init_predefined);
}
/**
* Get deprecated file ids.
*
* @return array Ids of the deprecated files.
*/
public static function getDeprecatedFilesIds($project)
{
$ptags = self::getDownloadTags($project);
$dtag = array_pop($ptags); // The last tag is the deprecated tag.
$sql = new Pluf_SQL('project=%s AND idf_tag_id=%s', array($project->id,
$dtag->id));
$ids = array();
foreach (Pluf::factory('IDF_Upload')->getList(array('filter' => $sql->gen(), 'view' => 'join_tags'))
as $file) {
$ids[] = (int) $file->id;
}
return $ids;
}
}
/**
* Display the summary of a download, then on a new line, display the
* list of labels.
*
* The summary of the download is linking to the download.
*/
function IDF_Views_Download_SummaryAndLabels($field, $down, $extra='')
{
$tags = array();
foreach ($down->get_tags_list() as $tag) {
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::listLabel',
array($down->shortname, $tag->id));
$tags[] = sprintf('<a href="%s" class="label">%s</a>', $url, Pluf_esc((string) $tag));
}
$out = '';
if (count($tags)) {
$out = '<br /><span class="note">'.implode(', ', $tags).'</span>';
}
return Pluf_esc($down->summary).$out;
}
function IDF_Views_Download_Size($field, $down)
{
return Pluf_Utils::prettySize($down->$field);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,655 @@
<?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 ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
Pluf::loadFunction('Pluf_Shortcuts_RenderToResponse');
Pluf::loadFunction('Pluf_Shortcuts_GetObjectOr404');
Pluf::loadFunction('Pluf_Shortcuts_GetFormForModel');
/**
* Project's views.
*/
class IDF_Views_Project
{
/**
* Home page of a project.
*/
public $logo_precond = array('IDF_Precondition::baseAccess');
public function logo($request, $match)
{
$prj = $request->project;
$logo = $prj->getConf()->getVal('logo');
if (empty($logo)) {
$url = Pluf::f('url_media') . '/idf/img/no_logo.png';
return new Pluf_HTTP_Response_Redirect($url);
}
$info = IDF_FileUtil::getMimeType($logo);
return new Pluf_HTTP_Response_File(Pluf::f('upload_path') . '/' . $prj->shortname . $logo,
$info[0]);
}
/**
* Home page of a project.
*/
public $home_precond = array('IDF_Precondition::baseAccess');
public function home($request, $match)
{
$prj = $request->project;
$team = $prj->getMembershipData();
$title = (string) $prj;
$downloads = array();
if ($request->rights['hasDownloadsAccess']) {
$tags = IDF_Views_Download::getDownloadTags($prj);
// the first tag is the featured, the last is the deprecated.
$downloads = $tags[0]->get_idf_upload_list();
}
$pages = array();
if ($request->rights['hasWikiAccess']) {
$tags = IDF_Views_Wiki::getWikiTags($prj);
$pages = $tags[0]->get_idf_wiki_page_list();
}
return Pluf_Shortcuts_RenderToResponse('idf/project/home.html',
array(
'page_title' => $title,
'team' => $team,
'downloads' => $downloads,
'pages' => $pages,
),
$request);
}
/**
* Returns an associative array with all accessible model filters
*
* @return array
*/
private static function getAccessibleModelFilters($request)
{
$filters = array('all' => __('All Updates'));
if (true === IDF_Precondition::accessSource($request))
$filters['commits'] = __('Commits');
if (true === IDF_Precondition::accessIssues($request))
$filters['issues'] = __('Issues and Comments');
if (true === IDF_Precondition::accessDownloads($request))
$filters['downloads'] = __('Downloads');
if (true === IDF_Precondition::accessWiki($request))
$filters['documents'] = __('Documents');
if (true === IDF_Precondition::accessReview($request))
$filters['reviews'] = __('Reviews and Patches');
return $filters;
}
/**
* Returns an array of model classes for which the current user
* has rights and which should be used according to his filter
*
* @param object $request
* @param string $model_filter
* @return array
*/
private static function determineModelClasses($request, $model_filter = 'all')
{
$classes = array();
if (true === IDF_Precondition::accessSource($request) &&
($model_filter == 'all' || $model_filter == 'commits')) {
$classes[] = '\'IDF_Commit\'';
// FIXME: this looks like a hack...
IDF_Scm::syncTimeline($request->project);
}
if (true === IDF_Precondition::accessIssues($request) &&
($model_filter == 'all' || $model_filter == 'issues')) {
$classes[] = '\'IDF_Issue\'';
$classes[] = '\'IDF_IssueComment\'';
}
if (true === IDF_Precondition::accessDownloads($request) &&
($model_filter == 'all' || $model_filter == 'downloads')) {
$classes[] = '\'IDF_Upload\'';
}
if (true === IDF_Precondition::accessWiki($request) &&
($model_filter == 'all' || $model_filter == 'documents')) {
$classes[] = '\'IDF_Wiki_Page\'';
$classes[] = '\'IDF_Wiki_PageRevision\'';
$classes[] = '\'IDF_Wiki_Resource\'';
$classes[] = '\'IDF_Wiki_ResourceRevision\'';
}
if (true === IDF_Precondition::accessReview($request) &&
($model_filter == 'all' || $model_filter == 'reviews')) {
$classes[] = '\'IDF_Review_Comment\'';
$classes[] = '\'IDF_Review_Patch\'';
}
if (count($classes) == 0) {
$classes[] = '\'IDF_Dummy\'';
}
return $classes;
}
/**
* This action serves as URI compatibility layer for v1.0.
*
* @deprecated
*/
public function timelineCompat($request, $match)
{
$match[2] = 'all';
return $this->timeline($request, $match);
}
/**
* Timeline of the project.
*/
public $timeline_precond = array('IDF_Precondition::baseAccess');
public function timeline($request, $match)
{
$prj = $request->project;
$model_filter = @$match[2];
$accessible_model_filters = self::getAccessibleModelFilters($request);
if (!array_key_exists($model_filter, $accessible_model_filters)) {
$model_filter = 'all';
}
$title = (string)$prj . ' ' . $accessible_model_filters[$model_filter];
$pag = new IDF_Timeline_Paginator(new IDF_Timeline());
$pag->class = 'recent-issues';
$pag->item_extra_props = array('request' => $request);
$pag->summary = __('This table shows the project updates.');
$classes = self::determineModelClasses($request, $model_filter);
$sql = sprintf('model_class IN (%s)', implode(', ', $classes));
$pag->forced_where = new Pluf_SQL('project=%s AND '.$sql,
array($prj->id));
$pag->sort_order = array('creation_dtime', 'ASC');
$pag->sort_reverse_order = array('creation_dtime');
$pag->action = array('IDF_Views_Project::timeline', array($prj->shortname, $model_filter));
$list_display = array(
'creation_dtime' => __('Age'),
'id' => __('Change'),
);
$pag->configure($list_display, array(), array('creation_dtime'));
$pag->items_per_page = 20;
$pag->no_results_text = __('No changes were found.');
$pag->setFromRequest($request);
if (!$request->user->isAnonymous() and $prj->isRestricted()) {
$feedurl = Pluf_HTTP_URL_urlForView('idf_project_timeline_feed_auth',
array($prj->shortname,
$model_filter,
IDF_Precondition::genFeedToken($prj, $request->user)));
} else {
$feedurl = Pluf_HTTP_URL_urlForView('idf_project_timeline_feed',
array($prj->shortname, $model_filter));
}
return Pluf_Shortcuts_RenderToResponse('idf/project/timeline.html',
array(
'page_title' => $title,
'feedurl' => $feedurl,
'timeline' => $pag,
'model_filter' => $model_filter,
'accessible_model_filters' => $accessible_model_filters,
),
$request);
}
/**
* This action serves as URI compatibility layer for v1.0.
*
* @deprecated
*/
public function timelineFeedCompat($request, $match)
{
$match[2] = 'all';
return $this->timelineFeed($request, $match);
}
/**
* Timeline feed.
*
* A custom view to have a bit more control on the way to handle
* it and optimize the output.
*
*/
public $timelineFeed_precond = array('IDF_Precondition::feedSetUser',
'IDF_Precondition::baseAccess');
public function timelineFeed($request, $match)
{
$prj = $request->project;
$model_filter = @$match[2];
$accessible_model_filters = self::getAccessibleModelFilters($request);
if (!array_key_exists($model_filter, $accessible_model_filters)) {
$model_filter = 'all';
}
$title = $accessible_model_filters[$model_filter];
$classes = self::determineModelClasses($request, $model_filter);
$sqls = sprintf('model_class IN (%s)', implode(', ', $classes));
$sql = new Pluf_SQL('project=%s AND '.$sqls, array($prj->id));
$params = array(
'filter' => $sql->gen(),
'order' => 'creation_dtime DESC',
'nb' => 20,
);
$items = Pluf::factory('IDF_Timeline')->getList($params);
$set = new Pluf_Model_Set($items,
array('public_dtime' => 'public_dtime'));
$out = array();
foreach ($set as $item) {
if ($item->id) {
$out[] = $item->feedFragment($request);
}
}
if ($items->count() > 0) {
$date = Pluf_Date::gmDateToGmString($items[0]->creation_dtime);
} else {
$date = gmdate('c');
}
$out = Pluf_Template::markSafe(implode("\n", $out));
$tmpl = new Pluf_Template('idf/index.atom');
$feedurl = Pluf::f('url_base').Pluf::f('idf_base').$request->query;
$viewurl = Pluf_HTTP_URL_urlForView('IDF_Views_Project::timeline',
array($prj->shortname, $model_filter));
$context = new Pluf_Template_Context_Request($request,
array('body' => $out,
'date' => $date,
'title' => $title,
'feedurl' => $feedurl,
'viewurl' => $viewurl));
return new Pluf_HTTP_Response('<?xml version="1.0" encoding="utf-8"?>'
."\n".$tmpl->render($context),
'application/atom+xml; charset=utf-8');
}
/**
* Administrate the summary of a project.
*/
public $admin_precond = array('IDF_Precondition::projectOwner');
public function admin($request, $match)
{
$prj = $request->project;
$title = sprintf(__('%s Project Summary'), (string) $prj);
$extra = array('project' => $prj, 'user' => $request->user);
if ($request->method == 'POST') {
$form = new IDF_Form_ProjectConf(array_merge($request->POST,
$request->FILES),
$extra);
if ($form->isValid()) {
$form->save();
$request->user->setMessage(__('The project has been updated.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::admin',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_ProjectConf(null, $extra);
}
$logo = $prj->getConf()->getVal('logo');
$arrays = self::autoCompleteArrays();
return Pluf_Shortcuts_RenderToResponse('idf/admin/summary.html',
array_merge(
array(
'page_title' => $title,
'form' => $form,
'project' => $prj,
'logo' => $logo,
),
$arrays
),
$request);
}
/**
* Administrate the issue tracking of a project.
*/
public $adminIssues_precond = array('IDF_Precondition::projectOwner');
public function adminIssues($request, $match)
{
$prj = $request->project;
$title = sprintf(__('%s Issue Tracking Configuration'), (string) $prj);
$conf = new IDF_Conf();
$conf->setProject($prj);
if ($request->method == 'POST') {
$form = new IDF_Form_IssueTrackingConf($request->POST);
if ($form->isValid()) {
foreach ($form->cleaned_data as $key=>$val) {
$conf->setVal($key, $val);
}
$request->user->setMessage(__('The issue tracking configuration has been saved.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminIssues',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$params = array();
$keys = array('labels_issue_template',
'labels_issue_open', 'labels_issue_closed',
'labels_issue_predefined', 'labels_issue_one_max',
'issue_relations');
foreach ($keys as $key) {
$_val = $conf->getVal($key, false);
if ($_val !== false) {
$params[$key] = $_val;
}
}
if (count($params) == 0) {
$params = null; //Nothing in the db, so new form.
}
$form = new IDF_Form_IssueTrackingConf($params);
}
return Pluf_Shortcuts_RenderToResponse('idf/admin/issue-tracking.html',
array(
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* Administrate the downloads of a project.
*/
public $adminDownloads_precond = array('IDF_Precondition::projectOwner');
public function adminDownloads($request, $match)
{
$prj = $request->project;
$title = sprintf(__('%s Downloads Configuration'), (string) $prj);
$conf = new IDF_Conf();
$conf->setProject($prj);
$extra = array(
'conf' => $conf,
);
if ($request->method == 'POST') {
$form = new IDF_Form_UploadConf($request->POST, $extra);
if ($form->isValid()) {
foreach ($form->cleaned_data as $key=>$val) {
$conf->setVal($key, $val);
}
$request->user->setMessage(__('The downloads configuration has been saved.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminDownloads',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$params = array();
$keys = array('labels_download_predefined', 'labels_download_one_max', 'upload_webhook_url');
foreach ($keys as $key) {
$_val = $conf->getVal($key, false);
if ($_val !== false) {
$params[$key] = $_val;
}
}
if (count($params) == 0) {
$params = null; //Nothing in the db, so new form.
}
$form = new IDF_Form_UploadConf($params, $extra);
}
return Pluf_Shortcuts_RenderToResponse('idf/admin/downloads.html',
array(
'page_title' => $title,
'form' => $form,
'hookkey' => $prj->getWebHookKey(),
),
$request);
}
/**
* Administrate the information pages of a project.
*/
public $adminWiki_precond = array('IDF_Precondition::projectOwner');
public function adminWiki($request, $match)
{
$prj = $request->project;
$title = sprintf(__('%s Documentation Configuration'), (string) $prj);
$conf = new IDF_Conf();
$conf->setProject($prj);
if ($request->method == 'POST') {
$form = new IDF_Form_WikiConf($request->POST);
if ($form->isValid()) {
foreach ($form->cleaned_data as $key=>$val) {
$conf->setVal($key, $val);
}
$request->user->setMessage(__('The documentation configuration has been saved.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminWiki',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$params = array();
$keys = array('labels_wiki_predefined', 'labels_wiki_one_max');
foreach ($keys as $key) {
$_val = $conf->getVal($key, false);
if ($_val !== false) {
$params[$key] = $_val;
}
}
if (count($params) == 0) {
$params = null; //Nothing in the db, so new form.
}
$form = new IDF_Form_WikiConf($params);
}
return Pluf_Shortcuts_RenderToResponse('idf/admin/wiki.html',
array(
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* Administrate the members of a project.
*/
public $adminMembers_precond = array('IDF_Precondition::projectOwner');
public function adminMembers($request, $match)
{
$prj = $request->project;
$title = sprintf(__('%s Project Members'), (string) $prj);
$params = array(
'project' => $prj,
'user' => $request->user,
);
if ($request->method == 'POST') {
$form = new IDF_Form_MembersConf($request->POST, $params);
if ($form->isValid()) {
$form->save();
$request->user->setMessage(__('The project membership has been saved.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminMembers',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_MembersConf($prj->getMembershipData('string'), $params);
}
return Pluf_Shortcuts_RenderToResponse('idf/admin/members.html',
array(
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* Administrate the access rights to the tabs.
*/
public $adminTabs_precond = array('IDF_Precondition::projectOwner');
public function adminTabs($request, $match)
{
$prj = $request->project;
$title = sprintf(__('%s Tabs Access Rights'), (string) $prj);
$extra = array(
'project' => $prj,
'conf' => $request->conf,
);
if ($request->method == 'POST') {
$form = new IDF_Form_TabsConf($request->POST, $extra);
if ($form->isValid()) {
foreach ($form->cleaned_data as $key=>$val) {
if (!in_array($key, array('private_project', 'authorized_users'))) {
$request->conf->setVal($key, $val);
}
}
$form->save(); // Save the authorized users.
$request->user->setMessage(__('The project tabs access rights and notification settings have been saved.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminTabs',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$params = array();
$sections = array('downloads', 'wiki', 'source', 'issues', 'review');
$keys = array();
foreach ($sections as $section) {
$keys[] = $section.'_access_rights';
$keys[] = $section.'_notification_owners_enabled';
$keys[] = $section.'_notification_members_enabled';
$keys[] = $section.'_notification_email_enabled';
$keys[] = $section.'_notification_email';
}
foreach ($keys as $key) {
$_val = $request->conf->getVal($key, false);
if ($_val !== false) {
$params[$key] = $_val;
}
}
// Add the authorized users.
$md = $prj->getMembershipData('string');
$params['authorized_users'] = $md['authorized'];
$params['private_project'] = $prj->private;
$form = new IDF_Form_TabsConf($params, $extra);
}
return Pluf_Shortcuts_RenderToResponse('idf/admin/tabs.html',
array(
'page_title' => $title,
'form' => $form,
'from_email' => Pluf::f('from_email'),
),
$request);
}
/**
* Administrate the source control.
*
* There, the login/password of the subversion remote repo can be
* change together with the webhook url.
*/
public $adminSource_precond = array('IDF_Precondition::projectOwner');
public function adminSource($request, $match)
{
$prj = $request->project;
$title = sprintf(__('%s Source'), (string) $prj);
$remote_svn = ($request->conf->getVal('scm') == 'svn' and
strlen($request->conf->getVal('svn_remote_url')) > 0);
$extra = array(
'conf' => $request->conf,
'remote_svn' => $remote_svn,
);
if ($request->method == 'POST') {
$form = new IDF_Form_SourceConf($request->POST, $extra);
if ($form->isValid()) {
foreach ($form->cleaned_data as $key=>$val) {
$request->conf->setVal($key, $val);
}
$request->user->setMessage(__('The project source configuration has been saved.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminSource',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$params = array();
foreach (array('svn_username', 'svn_password', 'webhook_url') as $key) {
$_val = $request->conf->getVal($key, false);
if ($_val !== false) {
$params[$key] = $_val;
}
}
if (count($params) == 0) {
$params = null; //Nothing in the db, so new form.
}
$form = new IDF_Form_SourceConf($params, $extra);
}
$scm = $request->conf->getVal('scm', 'git');
$options = array(
'git' => __('git'),
'svn' => __('Subversion'),
'mercurial' => __('mercurial'),
'mtn' => __('monotone'),
);
$repository_type = $options[$scm];
$hook_request_method = 'PUT';
if (Pluf::f('webhook_processing','') === 'compat') {
$hook_request_method = 'POST';
}
return Pluf_Shortcuts_RenderToResponse('idf/admin/source.html',
array(
'remote_svn' => $remote_svn,
'repository_access' => $prj->getRemoteAccessUrl(),
'repository_type' => $repository_type,
'repository_size' => $prj->getRepositorySize(),
'page_title' => $title,
'form' => $form,
'hookkey' => $prj->getWebHookKey(),
'hook_request_method' => $hook_request_method,
),
$request);
}
/**
* Create the autocomplete arrays for the little AJAX stuff.
*/
public static function autoCompleteArrays()
{
$forge = IDF_Forge::instance();
$labels = $forge->getProjectLabels(IDF_Form_Admin_LabelConf::init_project_labels);
$auto = array('auto_labels' => '');
$auto_raw = array('auto_labels' => $labels);
foreach ($auto_raw as $key => $st) {
$st = preg_split("/\015\012|\015|\012/", $st, -1, PREG_SPLIT_NO_EMPTY);
foreach ($st as $s) {
$v = '';
$d = '';
$_s = explode('=', $s, 2);
if (count($_s) > 1) {
$v = trim($_s[0]);
$d = trim($_s[1]);
} else {
$v = trim($_s[0]);
}
$auto[$key] .= sprintf('{ name: "%s", to: "%s" }, ',
Pluf_esc($d),
Pluf_esc($v));
}
$auto[$key] = substr($auto[$key], 0, -2);
}
return $auto;
}
}

View File

@@ -0,0 +1,235 @@
<?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 ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
Pluf::loadFunction('Pluf_Shortcuts_RenderToResponse');
Pluf::loadFunction('Pluf_Shortcuts_GetObjectOr404');
Pluf::loadFunction('Pluf_Shortcuts_GetFormForModel');
/**
* Review views.
*/
class IDF_Views_Review
{
/**
* View list of reviews for a given project.
*/
public $index_precond = array('IDF_Precondition::accessReview');
public function index($request, $match)
{
$prj = $request->project;
$title = sprintf(__('%s Code Reviews'), (string) $prj);
// Paginator to paginate the pages
$pag = new Pluf_Paginator(new IDF_Review());
$pag->class = 'recent-issues';
$pag->item_extra_props = array('project_m' => $prj,
'shortname' => $prj->shortname,
'current_user' => $request->user);
$pag->summary = __('This table shows the latest reviews.');
$pag->action = array('IDF_Views_Review::index', array($prj->shortname));
$otags = $prj->getTagIdsByStatus('open');
if (count($otags) == 0) $otags[] = 0;
$pag->forced_where = new Pluf_SQL('project=%s AND status IN ('.implode(', ', $otags).')', array($prj->id));
$pag->action = array('IDF_Views_Issue::index', array($prj->shortname));
$pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted
$pag->sort_reverse_order = array('modif_dtime');
$list_display = array(
'id' => __('Id'),
array('summary', 'IDF_Views_Review_SummaryAndLabels', __('Summary')),
array('status', 'IDF_Views_Issue_ShowStatus', __('Status')),
array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')),
);
$pag->configure($list_display, array(), array('title', 'modif_dtime'));
$pag->items_per_page = 25;
$pag->no_results_text = __('No reviews were found.');
$pag->sort_order = array('modif_dtime', 'ASC');
$pag->setFromRequest($request);
return Pluf_Shortcuts_RenderToResponse('idf/review/index.html',
array(
'page_title' => $title,
'reviews' => $pag,
),
$request);
}
/**
* Create a new code review.
*/
public $create_precond = array('IDF_Precondition::accessReview',
'Pluf_Precondition::loginRequired');
public function create($request, $match)
{
$prj = $request->project;
$title = __('Start Code Review');
if ($request->method == 'POST') {
$form = new IDF_Form_ReviewCreate(array_merge($request->POST,
$request->FILES),
array('project' => $prj,
'user' => $request->user
));
if ($form->isValid()) {
$review = $form->save();
$urlr = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
array($prj->shortname, $review->id));
$request->user->setMessage(sprintf(__('The <a href="%1$s">code review %2$d</a> has been created.'), $urlr, $review->id));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::index',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_ReviewCreate(null,
array('project' => $prj,
'user' => $request->user));
}
return Pluf_Shortcuts_RenderToResponse('idf/review/create.html',
array(
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* Download the patch of a review.
*/
public $getPatch_precond = array('IDF_Precondition::accessReview');
public function getPatch($request, $match)
{
$prj = $request->project;
$patch = Pluf_Shortcuts_GetObjectOr404('IDF_Review_Patch', $match[2]);
$prj->inOr404($patch->get_review());
$file = Pluf::f('upload_issue_path').'/'.$patch->patch;
$rep = new Pluf_HTTP_Response_File($file, 'text/plain');
$rep->headers['Content-Disposition'] = 'attachment; filename="'.$patch->id.'.diff"';
return $rep;
}
/**
* View a code review.
*/
public $view_precond = array('IDF_Precondition::accessReview');
public function view($request, $match)
{
$prj = $request->project;
$review = Pluf_Shortcuts_GetObjectOr404('IDF_Review', $match[2]);
$prj->inOr404($review);
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
array($prj->shortname, $review->id));
$title = Pluf_Template::markSafe(sprintf(__('Review <a href="%1$s">%2$d</a>: %3$s'), $url, $review->id, Pluf_esc($review->summary)));
$patches = $review->get_patches_list();
$patch = $patches[0];
$diff = new IDF_Diff(file_get_contents(Pluf::f('upload_issue_path').'/'.$patch->patch));
$diff->parse();
// The form to submit comments is based on the files in the
// diff
if ($request->method == 'POST' and !$request->user->isAnonymous()) {
$form = new IDF_Form_ReviewFileComment($request->POST,
array('files' => $diff->files,
'user' => $request->user,
'patch' => $patch,
'project' => $prj,
));
if ($form->isValid()) {
$review_comment = $form->save();
$review = $patch->get_review();
$urlr = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
array($prj->shortname, $review->id));
$request->user->setMessage(sprintf(__('Your <a href="%1$s">code review %2$d</a> has been published.'), $urlr, $review->id));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::index',
array($prj->shortname));
$review_comment->notify($request->conf);
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_ReviewFileComment(null,
array('files' => $diff->files,
'user' => $request->user,
'project' => $prj,
'patch' => $patch,));
}
$scm = IDF_Scm::get($request->project);
$files = array();
$reviewers = array();
foreach ($diff->files as $filename => $def) {
$fileinfo = $scm->getPathInfo($filename, $patch->get_commit()->scm_id);
$sql = new Pluf_SQL('cfile=%s', array($filename));
$cts = $patch->getFileComments(array('filter'=>$sql->gen(),
'order'=>'creation_dtime ASC'));
foreach ($cts as $ct) {
$reviewers[] = $ct->get_comment()->get_submitter();
}
if (count($def['chunks'])) {
$orig_file = ($fileinfo) ? $scm->getFile($fileinfo) : '';
$files[$filename] = array(
$diff->fileCompare($orig_file, $def, $filename),
$form->f->{md5($filename)},
$cts,
);
} else {
$files[$filename] = array('', $form->f->{md5($filename)}, $cts);
}
}
$reviewers = Pluf_Model_RemoveDuplicates($reviewers);
return Pluf_Shortcuts_RenderToResponse('idf/review/view.html',
array_merge(
array(
'page_title' => $title,
'review' => $review,
'files' => $files,
'diff' => $diff,
'patch' => $patch,
'comments' => $patch->get_comments_list(array('sort' => 'id ASC')),
'form' => $form,
'reviewers' => $reviewers,
),
IDF_Views_Issue::autoCompleteArrays($prj)
),
$request);
}
}
/**
* Display the summary of an review, then on a new line, display the
* list of labels with a link to a view "by label only".
*
* The summary of the review is linking to the review.
*/
function IDF_Views_Review_SummaryAndLabels($field, $review, $extra='')
{
$edit = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view',
array($review->shortname, $review->id));
$tags = array();
foreach ($review->get_tags_list() as $tag) {
$tags[] = Pluf_esc($tag);
}
$out = '';
if (count($tags)) {
$out = '<br /><span class="label note">'.implode(', ', $tags).'</span>';
}
return sprintf('<a href="%s">%s</a>', $edit, Pluf_esc($review->summary)).$out;
}

View File

@@ -0,0 +1,523 @@
<?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 ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
Pluf::loadFunction('Pluf_Shortcuts_RenderToResponse');
Pluf::loadFunction('Pluf_Shortcuts_GetObjectOr404');
Pluf::loadFunction('Pluf_Shortcuts_GetFormForModel');
/**
* View SCM repository.
*/
class IDF_Views_Source
{
/**
* Display help on how to checkout etc.
*/
public $help_precond = array('IDF_Precondition::accessSource');
public function help($request, $match)
{
$title = sprintf(__('%s Source Help'), (string) $request->project);
$scm = IDF_Scm::get($request->project);
$scmConf = $request->conf->getVal('scm', 'git');
$params = array(
'page_title' => $title,
'title' => $title,
'scm' => $scmConf,
);
return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/help.html',
$params, $request);
}
/**
* Is displayed in case an invalid revision is requested
*/
public $invalidRevision_precond = array('IDF_Precondition::accessSource');
public function invalidRevision($request, $match)
{
$title = sprintf(__('%s Invalid Revision'), (string) $request->project);
$scm = IDF_Scm::get($request->project);
$branches = $scm->getBranches();
$commit = $match[2];
$params = array(
'page_title' => $title,
'title' => $title,
'commit' => $commit,
'branches' => $branches,
);
$scmConf = $request->conf->getVal('scm', 'git');
return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/invalid_revision.html',
$params, $request);
}
/**
* Is displayed in case a revision identifier cannot be uniquely resolved
* to one single revision
*/
public $disambiguateRevision_precond = array('IDF_Precondition::accessSource',
'IDF_Views_Source_Precondition::scmAvailable');
public function disambiguateRevision($request, $match)
{
$title = sprintf(__('%s Ambiguous Revision'), (string) $request->project);
$commit = $match[2];
$redirect = $match[3];
$scm = IDF_Scm::get($request->project);
$revisions = $scm->disambiguateRevision($commit);
$params = array(
'page_title' => $title,
'title' => $title,
'commit' => $commit,
'revisions' => $revisions,
'redirect' => $redirect,
);
return Pluf_Shortcuts_RenderToResponse('idf/source/disambiguate_revision.html',
$params, $request);
}
public $changeLog_precond = array('IDF_Precondition::accessSource',
'IDF_Views_Source_Precondition::scmAvailable',
'IDF_Views_Source_Precondition::revisionValid');
public function changeLog($request, $match)
{
$scm = IDF_Scm::get($request->project);
$branches = $scm->getBranches();
$commit = $match[2];
$title = sprintf(__('%1$s %2$s Change Log'), (string) $request->project,
$this->getScmType($request));
$changes = $scm->getChangeLog($commit, 25);
$rchanges = array();
// Sync with the database
foreach ($changes as $change) {
$rchanges[] = IDF_Commit::getOrAdd($change, $request->project);
}
$rchanges = new Pluf_Template_ContextVars($rchanges);
$scmConf = $request->conf->getVal('scm', 'git');
$in_branches = $scm->inBranches($commit, '');
$tags = $scm->getTags();
$in_tags = $scm->inTags($commit, '');
return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/changelog.html',
array(
'page_title' => $title,
'title' => $title,
'changes' => $rchanges,
'commit' => $commit,
'branches' => $branches,
'tree_in' => $in_branches,
'tags' => $tags,
'tags_in' => $in_tags,
'scm' => $scmConf,
),
$request);
}
public function repository($request, $match)
{
$scm = IDF_Scm::get($request->project);
return $scm->repository($request, $match);
}
public $treeBase_precond = array('IDF_Precondition::accessSource',
'IDF_Views_Source_Precondition::scmAvailable',
'IDF_Views_Source_Precondition::revisionValid');
public function treeBase($request, $match)
{
$scm = IDF_Scm::get($request->project);
$commit = $match[2];
$cobject = $scm->getCommit($commit);
if (!$cobject) {
throw new Exception('could not retrieve commit object for '. $commit);
}
$title = sprintf(__('%1$s %2$s Source Tree'),
$request->project, $this->getScmType($request));
$branches = $scm->getBranches();
$in_branches = $scm->inBranches($commit, '');
$tags = $scm->getTags();
$in_tags = $scm->inTags($commit, '');
$cache = Pluf_Cache::factory();
$key = sprintf('Project:%s::IDF_Views_Source::treeBase:%s::',
$request->project->id, $commit);
if (null === ($res=$cache->get($key))) {
$res = new Pluf_Template_ContextVars($scm->getTree($commit));
$cache->set($key, $res);
}
$scmConf = $request->conf->getVal('scm', 'git');
$props = $scm->getProperties($commit);
$res->uasort(array('IDF_Views_Source', 'treeSort'));
return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/tree.html',
array(
'page_title' => $title,
'title' => $title,
'files' => $res,
'cobject' => $cobject,
'commit' => $commit,
'tree_in' => $in_branches,
'branches' => $branches,
'tags' => $tags,
'tags_in' => $in_tags,
'props' => $props,
),
$request);
}
public $tree_precond = array('IDF_Precondition::accessSource',
'IDF_Views_Source_Precondition::scmAvailable',
'IDF_Views_Source_Precondition::revisionValid');
public function tree($request, $match)
{
$scm = IDF_Scm::get($request->project);
$commit = $match[2];
$request_file = $match[3];
if (substr($request_file, -1) == '/') {
$request_file = substr($request_file, 0, -1);
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::tree',
array($match[1], $match[2],
$request_file));
return new Pluf_HTTP_Response_Redirect($url, 301);
}
$request_file_info = $scm->getPathInfo($request_file, $commit);
if (!$request_file_info) {
// Redirect to the main branch
$fburl = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
array($request->project->shortname,
$scm->getMainBranch()));
return new Pluf_HTTP_Response_Redirect($fburl);
}
$branches = $scm->getBranches();
$tags = $scm->getTags();
if ($request_file_info->type != 'tree') {
$info = self::getRequestedFileMimeType($request_file_info,
$commit, $scm);
if (!IDF_FileUtil::isText($info)) {
$rep = new Pluf_HTTP_Response($scm->getFile($request_file_info),
$info[0]);
$rep->headers['Content-Disposition'] = 'attachment; filename="'.$info[1].'"';
return $rep;
} else {
// We want to display the content of the file as text
$extra = array('branches' => $branches,
'tags' => $tags,
'commit' => $commit,
'request_file' => $request_file,
'request_file_info' => $request_file_info,
'mime' => $info,
);
return $this->viewFile($request, $match, $extra);
}
}
$bc = self::makeBreadCrumb($request->project, $commit, $request_file_info->fullpath);
$title = sprintf(__('%1$s %2$s Source Tree'),
$request->project, $this->getScmType($request));
$page_title = $bc.' - '.$title;
$cobject = $scm->getCommit($commit);
if (!$cobject) {
// Redirect to the first branch
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
array($request->project->shortname,
$scm->getMainBranch()));
return new Pluf_HTTP_Response_Redirect($url);
}
$in_branches = $scm->inBranches($commit, $request_file);
$in_tags = $scm->inTags($commit, $request_file);
$cache = Pluf_Cache::factory();
$key = sprintf('Project:%s::IDF_Views_Source::tree:%s::%s',
$request->project->id, $commit, $request_file);
if (null === ($res=$cache->get($key))) {
$res = new Pluf_Template_ContextVars($scm->getTree($commit, $request_file));
$cache->set($key, $res);
}
// try to find the previous level if it exists.
$prev = explode('/', $request_file);
$l = array_pop($prev);
$previous = substr($request_file, 0, -strlen($l.' '));
$scmConf = $request->conf->getVal('scm', 'git');
$props = $scm->getProperties($commit, $request_file);
$res->uasort(array('IDF_Views_Source', 'treeSort'));
return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/tree.html',
array(
'page_title' => $page_title,
'title' => $title,
'breadcrumb' => $bc,
'files' => $res,
'commit' => $commit,
'cobject' => $cobject,
'base' => $request_file_info->file,
'prev' => $previous,
'tree_in' => $in_branches,
'branches' => $branches,
'tags' => $tags,
'tags_in' => $in_tags,
'props' => $props,
),
$request);
}
public static function makeBreadCrumb($project, $commit, $file, $sep='/')
{
$elts = explode('/', $file);
$out = array();
$stack = '';
$i = 0;
foreach ($elts as $elt) {
$stack .= ($i==0) ? rawurlencode($elt) : '/'.rawurlencode($elt);
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::tree',
array($project->shortname,
$commit, $stack));
$out[] = '<a href="'.$url.'">'.Pluf_esc($elt).'</a>';
$i++;
}
return '<span class="breadcrumb">'.implode('<span class="sep">'.$sep.'</span>', $out).'</span>';
}
public $commit_precond = array('IDF_Precondition::accessSource',
'IDF_Views_Source_Precondition::scmAvailable',
'IDF_Views_Source_Precondition::revisionValid');
public function commit($request, $match)
{
$scm = IDF_Scm::get($request->project);
$commit = $match[2];
$large = $scm->isCommitLarge($commit);
$cobject = $scm->getCommit($commit, !$large);
if (!$cobject) {
throw new Exception('could not retrieve commit object for '. $commit);
}
$title = sprintf(__('%s Commit Details'), (string) $request->project);
$page_title = sprintf(__('%1$s Commit Details - %2$s'), (string) $request->project, $commit);
$rcommit = IDF_Commit::getOrAdd($cobject, $request->project);
$diff = new IDF_Diff($cobject->diff, $scm->getDiffPathStripLevel());
$cobject->diff = null;
$diff->parse();
$scmConf = $request->conf->getVal('scm', 'git');
$changes = $scm->getChanges($commit);
$branches = $scm->getBranches();
$in_branches = $scm->inBranches($cobject->commit, '');
$tags = $scm->getTags();
$in_tags = $scm->inTags($cobject->commit, '');
return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/commit.html',
array(
'page_title' => $page_title,
'title' => $title,
'diff' => $diff,
'cobject' => $cobject,
'commit' => $commit,
'changes' => $changes,
'branches' => $branches,
'tree_in' => $in_branches,
'tags' => $tags,
'tags_in' => $in_tags,
'scm' => $scmConf,
'rcommit' => $rcommit,
'large_commit' => $large,
),
$request);
}
public $downloadDiff_precond = array('IDF_Precondition::accessSource',
'IDF_Views_Source_Precondition::scmAvailable',
'IDF_Views_Source_Precondition::revisionValid');
public function downloadDiff($request, $match)
{
$scm = IDF_Scm::get($request->project);
$commit = $match[2];
$cobject = $scm->getCommit($commit, true);
if (!$cobject) {
throw new Exception('could not retrieve commit object for '. $commit);
}
$rep = new Pluf_HTTP_Response($cobject->diff, 'text/plain');
$rep->headers['Content-Disposition'] = 'attachment; filename="'.$commit.'.diff"';
return $rep;
}
/**
* Should only be called through self::tree
*/
public function viewFile($request, $match, $extra)
{
$title = sprintf(__('%1$s %2$s Source Tree'), (string) $request->project,
$this->getScmType($request));
$scm = IDF_Scm::get($request->project);
$branches = $extra['branches'];
$tags = $extra['tags'];
$commit = $extra['commit'];
$request_file = $extra['request_file'];
$request_file_info = $extra['request_file_info'];
$bc = self::makeBreadCrumb($request->project, $commit, $request_file_info->fullpath);
$page_title = $bc.' - '.$title;
$cobject = $scm->getCommit($commit);
$in_branches = $scm->inBranches($commit, $request_file);
$in_tags = $scm->inTags($commit, '');
// try to find the previous level if it exists.
$prev = explode('/', $request_file);
$l = array_pop($prev);
$previous = substr($request_file, 0, -strlen($l.' '));
$scmConf = $request->conf->getVal('scm', 'git');
$props = $scm->getProperties($commit, $request_file);
$content = IDF_FileUtil::highLight($extra['mime'], $scm->getFile($request_file_info));
return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/file.html',
array(
'page_title' => $page_title,
'title' => $title,
'breadcrumb' => $bc,
'file' => $content,
'commit' => $commit,
'cobject' => $cobject,
'fullpath' => $request_file,
'efullpath' => IDF_Scm::smartEncode($request_file),
'base' => $request_file_info->file,
'prev' => $previous,
'tree_in' => $in_branches,
'branches' => $branches,
'tags' => $tags,
'tags_in' => $in_tags,
'props' => $props,
),
$request);
}
/**
* Get a given file at a given commit.
*
*/
public $getFile_precond = array('IDF_Precondition::accessSource',
'IDF_Views_Source_Precondition::scmAvailable',
'IDF_Views_Source_Precondition::revisionValid');
public function getFile($request, $match)
{
$scm = IDF_Scm::get($request->project);
$commit = $match[2];
$request_file = $match[3];
$request_file_info = $scm->getPathInfo($request_file, $commit);
if (!$request_file_info or $request_file_info->type == 'tree') {
// Redirect to the first branch
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
array($request->project->shortname,
$scm->getMainBranch()));
return new Pluf_HTTP_Response_Redirect($url);
}
$info = self::getRequestedFileMimeType($request_file_info,
$commit, $scm);
$rep = new Pluf_HTTP_Response($scm->getFile($request_file_info),
$info[0]);
$rep->headers['Content-Disposition'] = 'attachment; filename="'.$info[1].'"';
return $rep;
}
/**
* Get a zip archive of the current commit.
*
*/
public $download_precond = array('IDF_Precondition::accessSource',
'IDF_Views_Source_Precondition::scmAvailable',
'IDF_Views_Source_Precondition::revisionValid');
public function download($request, $match)
{
$commit = trim($match[2]);
$scm = IDF_Scm::get($request->project);
$base = $request->project->shortname.'-'.$commit;
$rep = $scm->getArchiveStream($commit, $base.'/');
$rep->headers['Content-Transfer-Encoding'] = 'binary';
$rep->headers['Content-Disposition'] = 'attachment; filename="'.$base.'.zip"';
return $rep;
}
/**
* Find the mime type of a requested file.
*
* @param stdClass Request file info
* @param string Commit at which we want the file
* @param IDF_Scm SCM object
* @param array Mime type found or 'application/octet-stream', basename, extension
*/
public static function getRequestedFileMimeType($file_info, $commit, $scm)
{
$mime = IDF_FileUtil::getMimeType($file_info->file);
if ('application/octet-stream' != $mime[0]) {
return $mime;
}
return IDF_FileUtil::getMimeTypeFromContent($file_info->file,
$scm->getFile($file_info));
}
/**
* Callback function to sort tree entries
*/
public static function treeSort($a, $b)
{
// compare two nodes of the same type
if ($a->type === $b->type) {
if (mb_convert_case($a->file, MB_CASE_LOWER) <
mb_convert_case ($b->file, MB_CASE_LOWER)) {
return -1;
}
return 1;
}
// compare two nodes of different types, directories ("tree")
// should come before files ("blob")
if ($a->type > $b->type) {
return -1;
}
return 1;
}
/**
* Get the scm type for page title
*
* @return String
*/
private function getScmType($request)
{
return mb_convert_case($request->conf->getVal('scm', 'git'),
MB_CASE_TITLE, 'UTF-8');
}
}
function IDF_Views_Source_PrettySize($size)
{
return Pluf_Template::markSafe(str_replace(' ', '&nbsp;',
Pluf_Utils::prettySize($size)));
}
function IDF_Views_Source_PrettySizeSimple($size)
{
return Pluf_Utils::prettySize($size);
}
function IDF_Views_Source_ShortenString($string, $length)
{
$ellipse = "...";
$length = max(mb_strlen($ellipse) + 2, $length);
$preflen = ceil($length / 10);
if (mb_strlen($string) < $length)
return $string;
return mb_substr($string, 0, $preflen).$ellipse.
mb_substr($string, -($length - $preflen - mb_strlen($ellipse)));
}

View File

@@ -0,0 +1,74 @@
<?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 ***** */
class IDF_Views_Source_Precondition
{
/**
* Ensures that the configured SCM for the project is available
*
* @param $request
* @return true | Pluf_HTTP_Response_Redirect
*/
static public function scmAvailable($request)
{
$scm = IDF_Scm::get($request->project);
if (!$scm->isAvailable()) {
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::help',
array($request->project->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
return true;
}
/**
* Validates the revision given in the URL path and acts accordingly
*
* @param $request
* @return true | Pluf_HTTP_Response_Redirect
* @throws Exception
*/
static public function revisionValid($request)
{
list($url_info, $url_matches) = $request->view;
list(, $project, $commit) = $url_matches;
$scm = IDF_Scm::get($request->project);
$res = $scm->validateRevision($commit);
switch ($res) {
case IDF_Scm::REVISION_VALID:
return true;
case IDF_Scm::REVISION_INVALID:
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::invalidRevision',
array($request->project->shortname, $commit));
return new Pluf_HTTP_Response_Redirect($url);
case IDF_Scm::REVISION_AMBIGUOUS:
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::disambiguateRevision',
array($request->project->shortname,
$commit,
$url_info['model'].'::'.$url_info['method']));
return new Pluf_HTTP_Response_Redirect($url);
default:
throw new Exception('unknown validation result: '. $res);
}
}
}

View File

@@ -0,0 +1,84 @@
<?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 ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
/**
* View git repository.
*/
class IDF_Views_Source_Svn
{
/**
* Display tree of a specific SVN revision
*
*/
public function treeRev($request, $match)
{
$prj = $request->project;
if ($request->conf->getVal('scm', 'git') != 'svn') {
// Redirect to tree base if not svn
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
array($prj->shortname, $prj->getScmRoot()));
return new Pluf_HTTP_Response_Redirect($url);
}
// Get revision value
if (!isset($request->REQUEST['rev'])
or trim($request->REQUEST['rev']) == '') {
$scmRoot = $prj->getScmRoot();
} else {
$scmRoot = $request->REQUEST['rev'];
}
// Get source if not /
if (isset($request->REQUEST['sourcefile'])
and trim($request->REQUEST['sourcefile']) != '') {
$scmRoot .= '/'.$request->REQUEST['sourcefile'];
}
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase',
array($prj->shortname, $scmRoot));
return new Pluf_HTTP_Response_Redirect($url);
}
/**
* Display SVN changelog from specific revision
*
*/
public function changelogRev($request, $match)
{
$prj = $request->project;
if ($request->conf->getVal('scm', 'git') != 'svn') {
// Redirect to tree base if not svn
$scmRoot = $prj->getScmRoot();
} else {
// Get revision value if svn
if (!isset($request->REQUEST['rev'])
or trim($request->REQUEST['rev']) == '') {
$scmRoot = $prj->getScmRoot();
} else {
$scmRoot = $request->REQUEST['rev'];
}
}
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::changeLog',
array($prj->shortname, $scmRoot));
return new Pluf_HTTP_Response_Redirect($url);
}
}

View File

@@ -0,0 +1,293 @@
<?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 ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
Pluf::loadFunction('Pluf_Shortcuts_RenderToResponse');
/**
* User management views.
*
* Edit your account.
* Add emails for the link between a commit and an account.
*/
class IDF_Views_User
{
/**
* Dashboard of a user.
*
* Shows all the open issues assigned to the user.
*
* TODO: This views is a SQL horror. What needs to be done to cut
* by many the number of SQL queries:
* - Add a table to cache the open/closed status ids for all the
* projects.
* - Left join the issues with the project to get the shortname.
*
*/
public $dashboard_precond = array('Pluf_Precondition::loginRequired');
public function dashboard($request, $match, $working=true)
{
$otags = array();
// Note that this approach does not scale, we will need to add
// a table to cache the meaning of the tags for large forges.
foreach (IDF_Views::getProjects($request->user) as $project) {
$otags = array_merge($otags, $project->getTagIdsByStatus('open'));
}
if (count($otags) == 0) $otags[] = 0;
if ($working) {
$title = __('Your Dashboard - Working Issues');
$f_sql = new Pluf_SQL('owner=%s AND status IN ('.implode(', ', $otags).')', array($request->user->id));
} else {
$title = __('Your Dashboard - Submitted Issues');
$f_sql = new Pluf_SQL('submitter=%s AND status IN ('.implode(', ', $otags).')', array($request->user->id));
}
// Get stats about the issues
$sql = new Pluf_SQL('submitter=%s AND status IN ('.implode(', ', $otags).')', array($request->user->id));
$nb_submit = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen()));
$sql = new Pluf_SQL('owner=%s AND status IN ('.implode(', ', $otags).')', array($request->user->id));
$nb_owner = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen()));
// Paginator to paginate the issues
$pag = new Pluf_Paginator(new IDF_Issue());
$pag->class = 'recent-issues';
$pag->item_extra_props = array('current_user' => $request->user);
$pag->summary = __('This table shows the open issues.');
$pag->forced_where = $f_sql;
$pag->action = ($working) ? 'idf_dashboard' : 'idf_dashboard_submit';
$pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted
$pag->sort_reverse_order = array('modif_dtime');
$list_display = array(
'id' => __('Id'),
array('project', 'Pluf_Paginator_FkToString', __('Project')),
array('summary', 'IDF_Views_IssueSummaryAndLabels', __('Summary')),
array('status', 'IDF_Views_Issue_ShowStatus', __('Status')),
array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')),
);
$pag->configure($list_display, array(), array('status', 'modif_dtime'));
$pag->items_per_page = 10;
$pag->no_results_text = ($working) ? __('No issues are assigned to you, yeah!') : __('All the issues you submitted are fixed, yeah!');
$pag->setFromRequest($request);
return Pluf_Shortcuts_RenderToResponse('idf/user/dashboard.html',
array(
'page_title' => $title,
'nb_submit' => $nb_submit,
'nb_owner' => $nb_owner,
'issues' => $pag,
),
$request);
}
/**
* Simple management of the base info of the user.
*/
public $myAccount_precond = array('Pluf_Precondition::loginRequired');
public function myAccount($request, $match)
{
// As the password is salted, we can directly take the sha1 of
// the salted password.
$api_key = sha1($request->user->password);
$ext_pass = substr(sha1($request->user->password.Pluf::f('secret_key')), 0, 8);
$params = array('user' => $request->user);
if ($request->method == 'POST') {
$form = new IDF_Form_UserAccount(array_merge(
(array)$request->POST,
(array)$request->FILES
), $params);
if ($form->isValid()) {
$user = $form->save();
$url = Pluf_HTTP_URL_urlForView('IDF_Views_User::myAccount');
$request->session->setData('pluf_language', $user->language);
$request->user->setMessage(__('Your personal information has been updated.'));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$data = $request->user->getData();
unset($data['password']);
$form = new IDF_Form_UserAccount(null, $params);
}
$keys = $request->user->get_idf_key_list();
$mailaddrs = Pluf::factory('IDF_EmailAddress')->get_email_addresses_for_user($request->user);
return Pluf_Shortcuts_RenderToResponse('idf/user/myaccount.html',
array('page_title' => __('Your Account'),
'api_key' => $api_key,
'ext_pass' => $ext_pass,
'keys' => $keys,
'mailaddrs' => $mailaddrs,
'form' => $form),
$request);
}
/**
* Delete a public key.
*
* This is redirecting to the preferences
*/
public $deleteKey_precond = array('Pluf_Precondition::loginRequired');
public function deleteKey($request, $match)
{
$url = Pluf_HTTP_URL_urlForView('IDF_Views_User::myAccount');
if ($request->method == 'POST') {
$key = Pluf_Shortcuts_GetObjectOr404('IDF_Key', $match[1]);
if ($key->user != $request->user->id) {
return new Pluf_HTTP_Response_Forbidden($request);
}
$key->delete();
$request->user->setMessage(__('The public key has been deleted.'));
}
return new Pluf_HTTP_Response_Redirect($url);
}
/**
* Delete a mail address.
*
* This is redirecting to the preferences
*/
public $deleteMail_precond = array('Pluf_Precondition::loginRequired');
public function deleteMail($request, $match)
{
$url = Pluf_HTTP_URL_urlForView('IDF_Views_User::myAccount');
if ($request->method == 'POST') {
$address = Pluf_Shortcuts_GetObjectOr404('IDF_EmailAddress', $match[1]);
if ($address->user != $request->user->id) {
return new Pluf_HTTP_Response_Forbidden($request);
}
$address->delete();
$request->user->setMessage(__('The address has been deleted.'));
}
return new Pluf_HTTP_Response_Redirect($url);
}
/**
* Enter the key to change an email address.
*
* This is redirecting to changeEmailDo
*/
public $changeEmailInputKey_precond = array('Pluf_Precondition::loginRequired');
public function changeEmailInputKey($request, $match)
{
if ($request->method == 'POST') {
$form = new IDF_Form_UserChangeEmail($request->POST);
if ($form->isValid()) {
$url = $form->save();
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_UserChangeEmail();
}
return Pluf_Shortcuts_RenderToResponse('idf/user/changeemail.html',
array('page_title' => __('Confirm The Email Change'),
'form' => $form),
$request);
}
/**
* Really change the email address.
*/
public $changeEmailDo_precond = array('Pluf_Precondition::loginRequired');
public function changeEmailDo($request, $match)
{
$key = $match[1];
$url = Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailInputKey');
try {
list($email, $id, $time, $type) = IDF_Form_UserChangeEmail::validateKey($key);
} catch (Pluf_Form_Invalid $e) {
return new Pluf_HTTP_Response_Redirect($url);
}
if ($id != $request->user->id) {
return new Pluf_HTTP_Response_Redirect($url);
}
// Now we have a change link coming from the right user.
if ($type == "primary") {
$request->user->email = $email;
$request->user->update();
} else {
$mailaddress = new IDF_EmailAddress();
$mailaddress->user = $request->user;
$mailaddress->address = $email;
$mailaddress->create();
}
$request->user->setMessage(sprintf(__('Your new email address "%s" has been validated. Thank you!'), Pluf_esc($email)));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_User::myAccount');
return new Pluf_HTTP_Response_Redirect($url);
}
/**
* Public profile of a user.
*/
public function view($request, $match)
{
$sql = new Pluf_SQL('login=%s', array($match[1]));
$users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen()));
if (count($users) != 1 or !$users[0]->active) {
throw new Pluf_HTTP_Error404();
}
$user = $users[0];
$user_data = IDF_UserData::factory($user);
//$projects = $request->user->getAllPermissions();
//print_r($request->user->permissions);
//print_r($projects[0]);
//$projects = array();
//foreach (IDF_Views::getProjects($request->user) as $project) {
// $projects[] = $project;
//}
$projects = IDF_Views::getProjects($request->user);
//print_r($projects);
return Pluf_Shortcuts_RenderToResponse('idf/user/public.html',
array('page_title' => (string) $user,
'member' => $user,
'user_data' => $user_data,
'projects' => $projects
),
$request);
}
}
/**
* Display the summary of an issue, then on a new line, display the
* list of labels with a link to a view "by label only".
*
* The summary of the issue is linking to the issue.
*/
function IDF_Views_IssueSummaryAndLabels($field, $issue, $extra='')
{
$project = $issue->get_project();
$edit = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
array($project->shortname, $issue->id));
$tags = array();
foreach ($issue->get_tags_list() as $tag) {
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::listLabel',
array($project->shortname, $tag->id, 'open'));
$tags[] = sprintf('<a class="label" href="%s">%s</a>', $url, Pluf_esc((string) $tag));
}
$out = '';
if (count($tags)) {
$out = '<br /><span class="note">'.implode(', ', $tags).'</span>';
}
return sprintf('<a href="%s">%s</a>', $edit, Pluf_esc($issue->summary)).$out;
}

View File

@@ -0,0 +1,725 @@
<?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 ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
Pluf::loadFunction('Pluf_Shortcuts_RenderToResponse');
Pluf::loadFunction('Pluf_Shortcuts_GetObjectOr404');
Pluf::loadFunction('Pluf_Shortcuts_GetFormForModel');
/**
* Documentation pages views.
*/
class IDF_Views_Wiki
{
/**
* View list of pages for a given project.
*/
public $listPages_precond = array('IDF_Precondition::accessWiki');
public function listPages($request, $match, $api=false)
{
$prj = $request->project;
$title = sprintf(__('%s Documentation'), (string) $prj);
// Paginator to paginate the pages
$pag = new Pluf_Paginator(new IDF_Wiki_Page());
$pag->class = 'recent-issues';
$pag->item_extra_props = array('project_m' => $prj,
'shortname' => $prj->shortname,
'current_user' => $request->user);
$pag->summary = __('This table shows the documentation pages.');
$pag->action = array('IDF_Views_Wiki::listPages', array($prj->shortname));
$pag->edit_action = array('IDF_Views_Wiki::viewPage', 'shortname', 'title');
$sql = 'project=%s';
$ptags = self::getWikiTags($prj);
$dtag = array_pop($ptags); // The last tag is the deprecated tag.
$ids = self::getDeprecatedPagesIds($prj, $dtag);
if (count($ids)) {
$sql .= ' AND id NOT IN ('.implode(',', $ids).')';
}
$pag->forced_where = new Pluf_SQL($sql, array($prj->id));
$pag->extra_classes = array('right', '', 'a-c');
$list_display = array(
'title' => __('Page Title'),
array('summary', 'IDF_Views_Wiki_SummaryAndLabels', __('Summary')),
array('modif_dtime', 'Pluf_Paginator_DateYMD', __('Updated')),
);
$pag->configure($list_display, array(), array('title', 'modif_dtime'));
$pag->items_per_page = 25;
$pag->no_results_text = __('No documentation pages were found.');
$pag->sort_order = array('title', 'ASC');
$pag->setFromRequest($request);
return Pluf_Shortcuts_RenderToResponse('idf/wiki/listPages.html',
array(
'page_title' => $title,
'pages' => $pag,
'deprecated' => count($ids),
'dlabel' => $dtag,
),
$request);
}
/**
* View list of resources for a given project.
*/
public $listResources_precond = array('IDF_Precondition::accessWiki',
'Pluf_Precondition::loginRequired');
public function listResources($request, $match)
{
$prj = $request->project;
$title = sprintf(__('%s Documentation Resources'), (string) $prj);
$pag = new Pluf_Paginator(new IDF_Wiki_Resource());
$pag->class = 'recent-issues';
$pag->item_extra_props = array('project_m' => $prj,
'shortname' => $prj->shortname,
'current_user' => $request->user);
$pag->summary = __('This table shows the resources that can be used on documentation pages.');
$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', 'left', 'a-c');
$list_display = array(
'title' => __('Resource Title'),
'mime_type' => __('MIME type'),
'summary' => __('Description'),
array('modif_dtime', 'Pluf_Paginator_DateYMD', __('Updated')),
);
$pag->configure($list_display, array(), array('title', 'modif_dtime'));
$pag->items_per_page = 25;
$pag->no_results_text = __('No resources were found.');
$pag->sort_order = array('title', 'ASC');
$pag->setFromRequest($request);
return Pluf_Shortcuts_RenderToResponse('idf/wiki/listResources.html',
array(
'page_title' => $title,
'resources' => $pag,
),
$request);
}
public $search_precond = array('IDF_Precondition::accessWiki',);
public function search($request, $match)
{
$prj = $request->project;
if (!isset($request->REQUEST['q']) or trim($request->REQUEST['q']) == '') {
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listPages',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
$q = $request->REQUEST['q'];
$title = sprintf(__('Documentation Search - %s'), $q);
$pages = new Pluf_Search_ResultSet(IDF_Search::mySearch($q, $prj, 'IDF_Wiki_Page'));
if (count($pages) > 100) {
$pages->results = array_slice($pages->results, 0, 100);
}
$pag = new Pluf_Paginator();
$pag->items = $pages;
$pag->class = 'recent-issues';
$pag->item_extra_props = array('project_m' => $prj,
'shortname' => $prj->shortname,
'current_user' => $request->user);
$pag->summary = __('This table shows the pages found.');
$pag->action = array('IDF_Views_Wiki::search', array($prj->shortname), array('q'=> $q));
$pag->edit_action = array('IDF_Views_Wiki::viewPage', 'shortname', 'title');
$pag->extra_classes = array('right', '', 'a-c');
$list_display = array(
'title' => __('Page Title'),
array('summary', 'IDF_Views_Wiki_SummaryAndLabels', __('Summary')),
array('modif_dtime', 'Pluf_Paginator_DateYMD', __('Updated')),
);
$pag->configure($list_display);
$pag->items_per_page = 100;
$pag->no_results_text = __('No pages were found.');
$pag->setFromRequest($request);
$params = array('page_title' => $title,
'pages' => $pag,
'q' => $q,
);
return Pluf_Shortcuts_RenderToResponse('idf/wiki/search.html', $params, $request);
}
/**
* View list of pages with a given label.
*/
public $listPagesWithLabel_precond = array('IDF_Precondition::accessWiki');
public function listPagesWithLabel($request, $match)
{
$prj = $request->project;
$tag = Pluf_Shortcuts_GetObjectOr404('IDF_Tag', $match[2]);
$prj->inOr404($tag);
$title = sprintf(__('%1$s Documentation Pages with Label %2$s'), (string) $prj,
(string) $tag);
// Paginator to paginate the pages
$ptags = self::getWikiTags($prj);
$dtag = array_pop($ptags); // The last tag is the deprecated tag.
$pag = new Pluf_Paginator(new IDF_Wiki_Page());
$pag->model_view = 'join_tags';
$pag->class = 'recent-issues';
$pag->item_extra_props = array('project_m' => $prj,
'shortname' => $prj->shortname);
$pag->summary = sprintf(__('This table shows the documentation pages with label %s.'), (string) $tag);
$pag->forced_where = new Pluf_SQL('project=%s AND idf_tag_id=%s', array($prj->id, $tag->id));
$pag->action = array('IDF_Views_Wiki::listPagesWithLabel', array($prj->shortname, $tag->id));
$pag->edit_action = array('IDF_Views_Wiki::viewPage', 'shortname', 'title');
$pag->extra_classes = array('right', '', 'a-c');
$list_display = array(
'title' => __('Page Title'),
array('summary', 'IDF_Views_Wiki_SummaryAndLabels', __('Summary')),
array('modif_dtime', 'Pluf_Paginator_DateYMD', __('Updated')),
);
$pag->configure($list_display, array(), array('title', 'modif_dtime'));
$pag->items_per_page = 25;
$pag->no_results_text = __('No documentation pages were found.');
$pag->setFromRequest($request);
return Pluf_Shortcuts_RenderToResponse('idf/wiki/listPages.html',
array(
'page_title' => $title,
'label' => $tag,
'pages' => $pag,
'dlabel' => $dtag,
),
$request);
}
/**
* Create a new documentation page.
*/
public $createPage_precond = array('IDF_Precondition::accessWiki',
'Pluf_Precondition::loginRequired');
public function createPage($request, $match)
{
$prj = $request->project;
$title = __('New Page');
$preview = false;
if ($request->method == 'POST') {
$form = new IDF_Form_WikiPageCreate($request->POST,
array('project' => $prj,
'user' => $request->user
));
if ($form->isValid() and !isset($request->POST['preview'])) {
$page = $form->save();
$urlpage = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewPage',
array($prj->shortname, $page->title));
$request->user->setMessage(sprintf(__('The page <a href="%1$s">%2$s</a> has been created.'),
$urlpage, Pluf_esc($page->title)));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listPages',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
} elseif (isset($request->POST['preview'])) {
$preview = $request->POST['content'];
}
} else {
$pagename = (isset($request->GET['name'])) ?
$request->GET['name'] : '';
$form = new IDF_Form_WikiPageCreate(null,
array('name' => $pagename,
'project' => $prj,
'user' => $request->user));
}
return Pluf_Shortcuts_RenderToResponse('idf/wiki/createPage.html',
array(
'auto_labels' => self::autoCompleteArrays($prj),
'page_title' => $title,
'form' => $form,
'preview' => $preview,
),
$request);
}
/**
* Create a new resource.
*/
public $createResource_precond = array('IDF_Precondition::accessWiki',
'Pluf_Precondition::loginRequired');
public function createResource($request, $match)
{
$prj = $request->project;
$title = __('New Resource');
$preview = false;
if ($request->method == 'POST') {
$form = new IDF_Form_WikiResourceCreate(array_merge($request->POST, $request->FILES),
array('project' => $prj, 'user' => $request->user));
if ($form->isValid()) {
$resource = $form->save();
$urlresource = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource',
array($prj->shortname, $resource->title));
$request->user->setMessage(sprintf(__('The resource <a href="%1$s">%2$s</a> has been created.'), $urlresource, Pluf_esc($resource->title)));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listResources',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$resourcename = (isset($request->GET['name'])) ?
$request->GET['name'] : '';
$form = new IDF_Form_WikiResourceCreate(null,
array('name' => $resourcename,
'project' => $prj, 'user' => $request->user));
}
return Pluf_Shortcuts_RenderToResponse('idf/wiki/createResource.html',
array(
'page_title' => $title,
'form' => $form,
),
$request);
}
/**
* View a documentation page.
*/
public $viewPage_precond = array('IDF_Precondition::accessWiki');
public function viewPage($request, $match)
{
$prj = $request->project;
// Find the page
$sql = new Pluf_SQL('project=%s AND title=%s',
array($prj->id, $match[2]));
$pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen()));
if ($pages->count() != 1) {
return new Pluf_HTTP_Response_NotFound($request);
}
$page = $pages[0];
$revision = $page->get_current_revision();
// We grab the old revision if requested.
if (isset($request->GET['rev']) and preg_match('/^[0-9]+$/', $request->GET['rev'])) {
$revision = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_PageRevision',
$request->GET['rev']);
if ($revision->wikipage != $page->id) {
return new Pluf_HTTP_Response_NotFound($request);
}
}
$ptags = self::getWikiTags($prj);
$dtag = array_pop($ptags); // The last tag is the deprecated tag.
$tags = $page->get_tags_list();
$dep = Pluf_Model_InArray($dtag, $tags);
$title = $page->title;
$false = Pluf_DB_BooleanToDb(false, $page->getDbConnection());
$revs = $page->get_revisions_list(array('order' => 'creation_dtime DESC',
'filter' => 'is_head='.$false));
return Pluf_Shortcuts_RenderToResponse('idf/wiki/viewPage.html',
array(
'page_title' => $title,
'page' => $page,
'rev' => $revision,
'revs' => $revs,
'tags' => $tags,
'deprecated' => $dep,
),
$request);
}
/**
* View a documentation resource.
*/
public $viewResource_precond = array('IDF_Precondition::accessWiki');
public function viewResource($request, $match)
{
$prj = $request->project;
$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];
$revision = $resource->get_current_revision();
// grab the old revision if requested.
if (isset($request->GET['rev']) and preg_match('/^[0-9]+$/', $request->GET['rev'])) {
$revision = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_ResourceRevision',
$request->GET['rev']);
if ($revision->wikiresource != $resource->id) {
return new Pluf_HTTP_Response_NotFound($request);
}
}
$pagerevs = $revision->getPageRevisions();
$title = $resource->title;
$false = Pluf_DB_BooleanToDb(false, $resource->getDbConnection());
$revs = $resource->get_revisions_list(array('order' => 'creation_dtime DESC',
'filter' => 'is_head='.$false));
return Pluf_Shortcuts_RenderToResponse('idf/wiki/viewResource.html',
array(
'page_title' => $title,
'resource' => $resource,
'rev' => $revision,
'revs' => $revs,
'pagerevs' => $pagerevs,
),
$request);
}
/**
* Returns a bytestream to the given raw resource revision
*/
public $rawResource_precond = array('IDF_Precondition::accessWiki');
public function rawResource($request, $match)
{
$prj = $request->project;
$rev = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_ResourceRevision',
$match[2]);
$res = $rev->get_wikiresource();
if ($res->get_project()->id != $prj->id) {
return new Pluf_HTTP_Response_NotFound($request);
}
$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;
}
/**
* Remove a revision of a page.
*/
public $deletePageRev_precond = array('IDF_Precondition::accessWiki',
'IDF_Precondition::projectMemberOrOwner');
public function deletePageRev($request, $match)
{
$prj = $request->project;
$oldrev = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_PageRevision', $match[2]);
$page = $oldrev->get_wikipage();
$prj->inOr404($page);
if ($oldrev->is_head == true) {
return new Pluf_HTTP_Response_NotFound($request);
}
if ($request->method == 'POST') {
$oldrev->delete();
$request->user->setMessage(__('The old revision has been deleted.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewPage',
array($prj->shortname, $page->title));
return new Pluf_HTTP_Response_Redirect($url);
}
$title = sprintf(__('Delete Old Revision of %s'), $page->title);
$revision = $page->get_current_revision();
$false = Pluf_DB_BooleanToDb(false, $page->getDbConnection());
$revs = $page->get_revisions_list(array('order' => 'creation_dtime DESC',
'filter' => 'is_head='.$false));
return Pluf_Shortcuts_RenderToResponse('idf/wiki/deletePageRev.html',
array(
'page_title' => $title,
'page' => $page,
'oldrev' => $oldrev,
'rev' => $revision,
'revs' => $revs,
'tags' => $page->get_tags_list(),
),
$request);
}
/**
* Remove a revision of a resource.
*/
public $deleteResourceRev_precond = array('IDF_Precondition::accessWiki',
'IDF_Precondition::projectMemberOrOwner');
public function deleteResourceRev($request, $match)
{
$prj = $request->project;
$oldrev = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_ResourceRevision', $match[2]);
$resource = $oldrev->get_wikiresource();
$prj->inOr404($resource);
if ($oldrev->is_head == true) {
return new Pluf_HTTP_Response_NotFound($request);
}
if ($request->method == 'POST') {
$oldrev->delete();
$request->user->setMessage(__('The old revision has been deleted.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource',
array($prj->shortname, $resource->title));
return new Pluf_HTTP_Response_Redirect($url);
}
$title = sprintf(__('Delete Old Revision of %s'), $resource->title);
$false = Pluf_DB_BooleanToDb(false, $resource->getDbConnection());
$revs = $resource->get_revisions_list(array('order' => 'creation_dtime DESC',
'filter' => 'is_head='.$false));
return Pluf_Shortcuts_RenderToResponse('idf/wiki/deleteResourceRev.html',
array(
'page_title' => $title,
'resource' => $resource,
'oldrev' => $oldrev,
'revs' => $revs,
),
$request);
}
/**
* Update a documentation page.
*/
public $updatePage_precond = array('IDF_Precondition::accessWiki',
'Pluf_Precondition::loginRequired');
public function updatePage($request, $match)
{
$prj = $request->project;
// Find the page
$sql = new Pluf_SQL('project=%s AND title=%s',
array($prj->id, $match[2]));
$pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen()));
if ($pages->count() != 1) {
return new Pluf_HTTP_Response_NotFound($request);
}
$page = $pages[0];
$title = sprintf(__('Update %s'), $page->title);
$revision = $page->get_current_revision();
$preview = false;
$params = array('project' => $prj,
'user' => $request->user,
'page' => $page);
if ($request->method == 'POST') {
$form = new IDF_Form_WikiPageUpdate($request->POST, $params);
if ($form->isValid() and !isset($request->POST['preview'])) {
$page = $form->save();
$urlpage = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewPage',
array($prj->shortname, $page->title));
$request->user->setMessage(sprintf(__('The page <a href="%1$s">%2$s</a> has been updated.'),
$urlpage, Pluf_esc($page->title)));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listPages',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
} elseif (isset($request->POST['preview'])) {
$preview = $request->POST['content'];
}
} else {
$form = new IDF_Form_WikiPageUpdate(null, $params);
}
return Pluf_Shortcuts_RenderToResponse('idf/wiki/updatePage.html',
array(
'auto_labels' => self::autoCompleteArrays($prj),
'page_title' => $title,
'page' => $page,
'rev' => $revision,
'form' => $form,
'preview' => $preview,
),
$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="%1$s">%2$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.
*/
public $deletePage_precond = array('IDF_Precondition::accessWiki',
'IDF_Precondition::projectMemberOrOwner');
public function deletePage($request, $match)
{
$prj = $request->project;
$page = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_Page', $match[2]);
$prj->inOr404($page);
$params = array('page' => $page);
if ($request->method == 'POST') {
$form = new IDF_Form_WikiPageDelete($request->POST, $params);
if ($form->isValid()) {
$form->save();
$request->user->setMessage(__('The documentation page has been deleted.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listPages',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_WikiPageDelete(null, $params);
}
$title = sprintf(__('Delete Page %s'), $page->title);
$revision = $page->get_current_revision();
$false = Pluf_DB_BooleanToDb(false, $page->getDbConnection());
$revs = $page->get_revisions_list(array('order' => 'creation_dtime DESC',
'filter' => 'is_head='.$false));
return Pluf_Shortcuts_RenderToResponse('idf/wiki/deletePage.html',
array(
'page_title' => $title,
'page' => $page,
'form' => $form,
'rev' => $revision,
'revs' => $revs,
'tags' => $page->get_tags_list(),
),
$request);
}
/**
* Delete a Wiki resource.
*/
public $deleteResource_precond = array('IDF_Precondition::accessWiki',
'IDF_Precondition::projectMemberOrOwner');
public function deleteResource($request, $match)
{
$prj = $request->project;
$resource = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_Resource', $match[2]);
$prj->inOr404($resource);
$params = array('resource' => $resource);
if ($request->method == 'POST') {
$form = new IDF_Form_WikiResourceDelete($request->POST, $params);
if ($form->isValid()) {
$form->save();
$request->user->setMessage(__('The documentation resource has been deleted.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listResources',
array($prj->shortname));
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_WikiResourceDelete(null, $params);
}
$title = sprintf(__('Delete Resource %s'), $resource->title);
$revision = $resource->get_current_revision();
$false = Pluf_DB_BooleanToDb(false, $resource->getDbConnection());
$revs = $resource->get_revisions_list(array('order' => 'creation_dtime DESC',
'filter' => 'is_head='.$false));
return Pluf_Shortcuts_RenderToResponse('idf/wiki/deleteResource.html',
array(
'page_title' => $title,
'resource' => $resource,
'form' => $form,
'rev' => $revision,
'revs' => $revs,
),
$request);
}
/**
* Get the wiki tags.
*
* @param IDF_Project
* @return ArrayObject The tags
*/
public static function getWikiTags($project)
{
return $project->getTagsFromConfig('labels_wiki_predefined',
IDF_Form_WikiConf::init_predefined);
}
/**
* Get deprecated page ids.
*
* @param IDF_Project
* @param IDF_Tag Deprecated tag (null)
* @return array Ids of the deprecated pages.
*/
public static function getDeprecatedPagesIds($project, $dtag=null)
{
if (is_null($dtag)) {
$ptags = self::getWikiTags($project);
$dtag = array_pop($ptags); // The last tag is the deprecated tag
}
$sql = new Pluf_SQL('project=%s AND idf_tag_id=%s', array($project->id,
$dtag->id));
$ids = array();
foreach (Pluf::factory('IDF_Wiki_Page')->getList(array('filter' => $sql->gen(), 'view' => 'join_tags'))
as $file) {
$ids[] = (int) $file->id;
}
return $ids;
}
/**
* Create the autocomplete arrays for the little AJAX stuff.
*/
public static function autoCompleteArrays($project)
{
$conf = new IDF_Conf();
$conf->setProject($project);
$st = preg_split("/\015\012|\015|\012/",
$conf->getVal('labels_wiki_predefined', IDF_Form_WikiConf::init_predefined), -1, PREG_SPLIT_NO_EMPTY);
$auto = '';
foreach ($st as $s) {
$v = '';
$d = '';
$_s = explode('=', $s, 2);
if (count($_s) > 1) {
$v = trim($_s[0]);
$d = trim($_s[1]);
} else {
$v = trim($_s[0]);
}
$auto .= sprintf('{ name: "%s", to: "%s" }, ',
Pluf_esc($d), Pluf_esc($v));
}
return substr($auto, 0, -2);
}
}
/**
* Display the summary of a page, then on a new line, display the
* list of labels.
*/
function IDF_Views_Wiki_SummaryAndLabels($field, $page, $extra='')
{
$tags = array();
foreach ($page->get_tags_list() as $tag) {
$tags[] = Pluf_esc((string) $tag);
}
$out = '';
if (count($tags)) {
$out = '<br /><span class="note label">'.implode(', ', $tags).'</span>';
}
return Pluf_esc($page->summary).$out;
}