Initial commit
This commit is contained in:
649
indefero/src/IDF/Views/Admin.php
Normal file
649
indefero/src/IDF/Views/Admin.php
Normal 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;
|
||||
}
|
131
indefero/src/IDF/Views/Api.php
Normal file
131
indefero/src/IDF/Views/Api.php
Normal 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();
|
||||
}
|
||||
}
|
425
indefero/src/IDF/Views/Download.php
Normal file
425
indefero/src/IDF/Views/Download.php
Normal 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);
|
||||
}
|
1055
indefero/src/IDF/Views/Issue.php
Normal file
1055
indefero/src/IDF/Views/Issue.php
Normal file
File diff suppressed because it is too large
Load Diff
655
indefero/src/IDF/Views/Project.php
Normal file
655
indefero/src/IDF/Views/Project.php
Normal 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;
|
||||
}
|
||||
}
|
235
indefero/src/IDF/Views/Review.php
Normal file
235
indefero/src/IDF/Views/Review.php
Normal 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;
|
||||
}
|
||||
|
523
indefero/src/IDF/Views/Source.php
Normal file
523
indefero/src/IDF/Views/Source.php
Normal 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(' ', ' ',
|
||||
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)));
|
||||
}
|
74
indefero/src/IDF/Views/Source/Precondition.php
Normal file
74
indefero/src/IDF/Views/Source/Precondition.php
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
84
indefero/src/IDF/Views/Source/Svn.php
Normal file
84
indefero/src/IDF/Views/Source/Svn.php
Normal 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);
|
||||
}
|
||||
}
|
293
indefero/src/IDF/Views/User.php
Normal file
293
indefero/src/IDF/Views/User.php
Normal 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;
|
||||
}
|
725
indefero/src/IDF/Views/Wiki.php
Normal file
725
indefero/src/IDF/Views/Wiki.php
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user