Merge branch 'stable' of https://github.com/kanboard/kanboard
This commit is contained in:
commit
fe8e9cdcfe
|
|
@ -1 +0,0 @@
|
|||
1 0 * * * cd /var/www/kanboard && ./kanboard cronjob >/dev/null 2>&1
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
user nginx;
|
||||
worker_processes 1;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
server_tokens off;
|
||||
access_log off;
|
||||
error_log /dev/stderr;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
index index.php;
|
||||
root /var/www/kanboard;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass unix:/var/run/php-fpm.sock;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
}
|
||||
|
||||
location /data {
|
||||
return 404;
|
||||
}
|
||||
|
||||
location ~* ^.+\.(log|sqlite)$ {
|
||||
return 404;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
return 404;
|
||||
}
|
||||
|
||||
location ~* ^.+\.(ico|jpg|gif|png|css|js|svg|eot|ttf|woff|woff2|otf)$ {
|
||||
expires 7d;
|
||||
etag on;
|
||||
}
|
||||
|
||||
client_max_body_size 32M;
|
||||
gzip on;
|
||||
gzip_comp_level 3;
|
||||
gzip_disable "msie6";
|
||||
gzip_vary on;
|
||||
gzip_types
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/json
|
||||
text/xml
|
||||
application/xml
|
||||
application/rss+xml
|
||||
text/css
|
||||
text/plain;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
expose_php = Off
|
||||
error_reporting = E_ALL
|
||||
display_errors = Off
|
||||
log_errors = On
|
||||
error_log = /dev/stderr
|
||||
date.timezone = UTC
|
||||
allow_url_fopen = On
|
||||
post_max_size = 30M
|
||||
upload_max_filesize = 30M
|
||||
opcache.max_accelerated_files = 7963
|
||||
opcache.validate_timestamps = Off
|
||||
opcache.save_comments = 0
|
||||
opcache.load_comments = 0
|
||||
opcache.fast_shutdown = 1
|
||||
opcache.enable_file_override = On
|
||||
always_populate_raw_post_data = -1
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
[global]
|
||||
error_log = /dev/stderr
|
||||
log_level = error
|
||||
daemonize = no
|
||||
|
||||
[www]
|
||||
env[DATABASE_URL] = $DATABASE_URL
|
||||
env[DEBUG] = $DEBUG
|
||||
env[LOG_DRIVER] = stderr
|
||||
|
||||
catch_workers_output = yes
|
||||
user = nginx
|
||||
group = nginx
|
||||
listen.owner = nginx
|
||||
listen.group = nginx
|
||||
listen = /var/run/php-fpm.sock
|
||||
pm = dynamic
|
||||
pm.max_children = 20
|
||||
pm.start_servers = 1
|
||||
pm.min_spare_servers = 1
|
||||
pm.max_spare_servers = 3
|
||||
pm.max_requests = 2048
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/sh
|
||||
/bin/true
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/execlineb -P
|
||||
nginx -g "daemon off;"
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/execlineb -P
|
||||
php-fpm -F
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
.git
|
||||
.git*
|
||||
.dockerignore
|
||||
.vagrant
|
||||
.idea
|
||||
data/*
|
||||
Makefile
|
||||
.*.yml
|
||||
*.yml
|
||||
*.js
|
||||
*.md
|
||||
*.sh
|
||||
app.json
|
||||
bower.json
|
||||
nitrous.json
|
||||
package.json
|
||||
Vagrantfile
|
||||
web.config
|
||||
Makefile
|
||||
bower_components
|
||||
node_modules
|
||||
|
|
@ -19,6 +19,6 @@ data/files
|
|||
data/cache
|
||||
/vendor
|
||||
*.bak
|
||||
!.docker/kanboard/config.php
|
||||
!docker/kanboard/config.php
|
||||
node_modules
|
||||
bower_components
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
filter:
|
||||
paths:
|
||||
- app/*
|
||||
excluded_paths:
|
||||
- app/Schema/*
|
||||
- app/Template/*
|
||||
- app/Locale/*
|
||||
- app/Library/*
|
||||
- app/constants.php
|
||||
- app/common.php
|
||||
- app/check_setup.php
|
||||
|
|
@ -0,0 +1 @@
|
|||
Read https://kanboard.net/documentation/contributing
|
||||
|
|
@ -11,11 +11,14 @@ Contributors:
|
|||
- [Ally Raza](https://github.com/alirz23)
|
||||
- [Angystardust](https://github.com/angystardust)
|
||||
- [Anjar Febrianto](https://github.com/Lasut)
|
||||
- [Anton](https://github.com/tester22)
|
||||
- [Ashbike](https://github.com/ashbike)
|
||||
- [Ashish Kulkarni](https://github.com/ashkulz)
|
||||
- [Biniou180](https://github.com/Biniou180)
|
||||
- [Bitcoin 333](https://github.com/bitcoin333)
|
||||
- [Busfreak](https://github.com/Busfreak)
|
||||
- [Christian González](https://github.com/nerdoc)
|
||||
- [Christopher Geelen](https://github.com/cdgeelen)
|
||||
- [Chorgroup](https://github.com/chorgroup)
|
||||
- Claudio Lobo
|
||||
- [Cluxter](https://github.com/cluxter)
|
||||
|
|
@ -44,15 +47,19 @@ Contributors:
|
|||
- [Gavlepeter](https://github.com/gavlepeter)
|
||||
- [Gerardo Zamudio](https://github.com/gerardozamudio)
|
||||
- [Goofy](https://github.com/goofy-bz)
|
||||
- [Hairetdin](https://github.com/hairetdin)
|
||||
- [Hendrik Stocker](https://github.com/hendrik-stoker)
|
||||
- [Honda2](https://github.com/honda2)
|
||||
- [Iterate From 0](https://github.com/freebsd-kanboard)
|
||||
- [Jan Dittrich](https://github.com/jdittrich)
|
||||
- [Janne Mäntyharju](https://github.com/JanneMantyharju)
|
||||
- [Jannik Winkel](https://github.com/kiney)
|
||||
- [Jean-François Magnier](https://github.com/lefakir)
|
||||
- [Jeff Guillou](https://github.com/jf-guillou)
|
||||
- [Jesusaplsoft](https://github.com/jesusaplsoft)
|
||||
- [Jesús Marín](https://github.com/alu0100502114)
|
||||
- [Jules Verhaeren](https://github.com/julesverhaeren)
|
||||
- [JunglaCODE]https://github.com/junglaCODE)
|
||||
- [Karol J](https://github.com/dzudek)
|
||||
- [Kiswa](https://github.com/kiswa)
|
||||
- [Kralo](https://github.com/kralo)
|
||||
|
|
@ -112,6 +119,7 @@ Contributors:
|
|||
- [StavrosKa](https://github.com/StavrosKa)
|
||||
- [Sylvain Veyrié](https://github.com/turb)
|
||||
- [Thomas Lutz](https://github.com/phoen1x)
|
||||
- [Thomas Stinner](https://github.com/stinnux)
|
||||
- [Timo](https://github.com/BlueTeck)
|
||||
- [Timotheus Pokorra](https://github.com/tpokorra)
|
||||
- [Tomáš Votruba](https://github.com/TomasVotruba)
|
||||
|
|
@ -125,6 +133,7 @@ Contributors:
|
|||
- [Vitaliy S. Orlov](https://github.com/orlov0562)
|
||||
- [Vladimir Babin](https://github.com/Chiliec)
|
||||
- [Yannick Ihmels](https://github.com/ihmels)
|
||||
- [Yakovenkov](https://github.com/yakovenkov)
|
||||
- [Ybarc](https://github.com/ybarc)
|
||||
- [Yu Yongwoo](https://github.com/uyu423)
|
||||
- [Yuichi Murata](https://github.com/yuichi1004)
|
||||
|
|
|
|||
79
ChangeLog
79
ChangeLog
|
|
@ -1,3 +1,82 @@
|
|||
Version 1.0.32
|
||||
--------------
|
||||
|
||||
New features:
|
||||
|
||||
* New automated actions:
|
||||
- Close tasks without activity in a specific column
|
||||
- Set due date automatically
|
||||
- Move a task to another column when closed
|
||||
- Move a task to another column when not moved during a given period
|
||||
* New filter "moved" for moved date of tasks
|
||||
* Added internal task links to activity stream
|
||||
* Added new event for removed comments
|
||||
* Added search filter for task priority
|
||||
* Added the possibility to hide tasks in dashboard for a specific column
|
||||
* Documentation translated in Russian
|
||||
|
||||
Improvements:
|
||||
|
||||
* Improve background worker and job handler
|
||||
* New template hooks
|
||||
* Removed individual column scrolling on board, columns use the height of all tasks
|
||||
* Improve project page titles
|
||||
* Remove sidebar titles when not necessary
|
||||
* Internal events management refactoring
|
||||
* Handle header X-Real-IP to get IP address
|
||||
* Display project name for task auto-complete fields
|
||||
* Make search attributes not case sensitive
|
||||
* Display TOTP issuer for 2FA
|
||||
* Make sure that the table schema_version use InnoDB for Mysql
|
||||
* Use the library PicoFeed to generate RSS/Atom feeds
|
||||
* Change all links to the new repository
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Allow users to see inactive projects
|
||||
* Fixed typo in template that prevent project permissions to be duplicated
|
||||
* Fixed search query with multiple assignees (nested OR conditions)
|
||||
* Fixed Markdown editor auto-grow on the task form (Safari)
|
||||
* Fixed compatibility issue with PHP 5.3 for OAuthUserProvider class
|
||||
|
||||
Version 1.0.31
|
||||
--------------
|
||||
|
||||
New features:
|
||||
|
||||
* Added tags: global and specific by project
|
||||
* Added application and project roles validation for API procedure calls
|
||||
* Added new API call: "getProjectByIdentifier"
|
||||
* Added new API calls for external task links, project attachments and subtask time tracking
|
||||
|
||||
Improvements:
|
||||
|
||||
* Use PHP 7 for the Docker image
|
||||
* Preserve role for existing users when using ReverseProxy authentication
|
||||
* Handle priority for task and project duplication
|
||||
* Expose task reference field to the user interface
|
||||
* Improve ICal export
|
||||
* Added argument owner_id and identifier to project API calls
|
||||
* Rewrite integration tests to run with Docker containers
|
||||
* Use the same task form layout everywhere
|
||||
* Removed some tasks dropdown menus that are now available with task edit form
|
||||
* Make embedded documentation readable in multiple languages (if a translation is available)
|
||||
* Added acceptance tests (browser tests)
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Fixed broken CSV exports
|
||||
* Fixed identical background color for LetterAvatar on 32bits platforms (Hash greater than PHP_MAX_INT)
|
||||
* Fixed lexer issue with non word characters
|
||||
* Flush memory cache in worker to get latest config values
|
||||
* Fixed empty title for web notification with only one overdue task
|
||||
* Take default swimlane into consideration for SwimlaneModel::getFirstActiveSwimlane()
|
||||
* Fixed "due today" highlighting
|
||||
|
||||
Breaking changes:
|
||||
|
||||
* Docker volume paths are changed to /var/www/app/{data,plugins}
|
||||
|
||||
Version 1.0.30
|
||||
--------------
|
||||
|
||||
|
|
|
|||
43
Dockerfile
43
Dockerfile
|
|
@ -1,36 +1,13 @@
|
|||
FROM alpine:3.4
|
||||
MAINTAINER Frederic Guillot <fred@kanboard.net>
|
||||
FROM fguillot/alpine-nginx-php7
|
||||
|
||||
RUN apk update && \
|
||||
apk add nginx bash ca-certificates s6 curl \
|
||||
php5-fpm php5-json php5-zlib php5-xml php5-dom php5-ctype php5-opcache php5-zip \
|
||||
php5-pdo php5-pdo_mysql php5-pdo_sqlite php5-pdo_pgsql php5-ldap \
|
||||
php5-gd php5-mcrypt php5-openssl php5-phar && \
|
||||
rm -rf /var/cache/apk/*
|
||||
COPY . /var/www/app
|
||||
COPY docker/kanboard/config.php /var/www/app/config.php
|
||||
COPY docker/crontab/cronjob.alpine /var/spool/cron/crontabs/nginx
|
||||
COPY docker/services.d/cron /etc/services.d/cron
|
||||
COPY docker/php/env.conf /etc/php7/php-fpm.d/env.conf
|
||||
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --filename=/usr/local/bin/composer
|
||||
RUN cd /var/www/app && composer --prefer-dist --no-dev --optimize-autoloader --quiet install
|
||||
RUN chown -R nginx:nginx /var/www/app/data /var/www/app/plugins
|
||||
|
||||
RUN cd /var/www \
|
||||
&& curl -LO https://github.com/fguillot/kanboard/archive/master.zip \
|
||||
&& unzip -qq master.zip \
|
||||
&& rm -f *.zip \
|
||||
&& mv kanboard-master kanboard \
|
||||
&& cd /var/www/kanboard && composer --prefer-dist --no-dev --optimize-autoloader --quiet install \
|
||||
&& chown -R nginx:nginx /var/www/kanboard \
|
||||
&& chown -R nginx:nginx /var/lib/nginx
|
||||
|
||||
COPY .docker/services.d /etc/services.d
|
||||
COPY .docker/php/conf.d/local.ini /etc/php5/conf.d/
|
||||
COPY .docker/php/php-fpm.conf /etc/php5/
|
||||
COPY .docker/nginx/nginx.conf /etc/nginx/
|
||||
COPY .docker/kanboard/config.php /var/www/kanboard/
|
||||
COPY .docker/kanboard/config.php /var/www/kanboard/
|
||||
COPY .docker/crontab/kanboard /var/spool/cron/crontabs/nginx
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
VOLUME /var/www/kanboard/data
|
||||
VOLUME /var/www/kanboard/plugins
|
||||
|
||||
ENTRYPOINT ["/bin/s6-svscan", "/etc/services.d"]
|
||||
CMD []
|
||||
VOLUME /var/www/app/data
|
||||
VOLUME /var/www/app/plugins
|
||||
|
|
|
|||
28
Makefile
28
Makefile
|
|
@ -9,7 +9,7 @@ static:
|
|||
archive:
|
||||
@ echo "Build archive: version=${version}, destination=${dst}"
|
||||
@ rm -rf ${BUILD_DIR}/kanboard ${BUILD_DIR}/kanboard-*.zip
|
||||
@ cd ${BUILD_DIR} && git clone --depth 1 -q https://github.com/fguillot/kanboard.git
|
||||
@ cd ${BUILD_DIR} && git clone --depth 1 -q https://github.com/kanboard/kanboard.git
|
||||
@ cd ${BUILD_DIR}/kanboard && composer --prefer-dist --no-dev --optimize-autoloader --quiet install
|
||||
@ rm -rf ${BUILD_DIR}/kanboard/data/*.sqlite
|
||||
@ rm -rf ${BUILD_DIR}/kanboard/data/*.log
|
||||
|
|
@ -26,7 +26,8 @@ archive:
|
|||
@ rm -rf ${BUILD_DIR}/kanboard/*.lock
|
||||
@ rm -rf ${BUILD_DIR}/kanboard/*.json
|
||||
@ rm -rf ${BUILD_DIR}/kanboard/*.js
|
||||
@ rm -rf ${BUILD_DIR}/kanboard/.docker
|
||||
@ rm -rf ${BUILD_DIR}/kanboard/.dockerignore
|
||||
@ rm -rf ${BUILD_DIR}/kanboard/docker
|
||||
@ rm -rf ${BUILD_DIR}/kanboard/nitrous*
|
||||
@ cd ${BUILD_DIR}/kanboard && find ./vendor -name doc -type d -exec rm -rf {} +;
|
||||
@ cd ${BUILD_DIR}/kanboard && find ./vendor -name notes -type d -exec rm -rf {} +;
|
||||
|
|
@ -58,7 +59,28 @@ test-postgres:
|
|||
unittest: test-sqlite test-mysql test-postgres
|
||||
|
||||
test-browser:
|
||||
@ phpunit -c tests/acceptance.xml
|
||||
@ phpunit -c tests/acceptance.xml
|
||||
|
||||
integration-test-mysql:
|
||||
@ composer install
|
||||
@ docker-compose -f tests/docker/compose.integration.mysql.yaml build
|
||||
@ docker-compose -f tests/docker/compose.integration.mysql.yaml up -d mysql app
|
||||
@ docker-compose -f tests/docker/compose.integration.mysql.yaml up tests
|
||||
@ docker-compose -f tests/docker/compose.integration.mysql.yaml down
|
||||
|
||||
integration-test-postgres:
|
||||
@ composer install
|
||||
@ docker-compose -f tests/docker/compose.integration.postgres.yaml build
|
||||
@ docker-compose -f tests/docker/compose.integration.postgres.yaml up -d postgres app
|
||||
@ docker-compose -f tests/docker/compose.integration.postgres.yaml up tests
|
||||
@ docker-compose -f tests/docker/compose.integration.postgres.yaml down
|
||||
|
||||
integration-test-sqlite:
|
||||
@ composer install
|
||||
@ docker-compose -f tests/docker/compose.integration.sqlite.yaml build
|
||||
@ docker-compose -f tests/docker/compose.integration.sqlite.yaml up -d app
|
||||
@ docker-compose -f tests/docker/compose.integration.sqlite.yaml up tests
|
||||
@ docker-compose -f tests/docker/compose.integration.sqlite.yaml down
|
||||
|
||||
sql:
|
||||
@ pg_dump --schema-only --no-owner --no-privileges --quote-all-identifiers -n public --file app/Schema/Sql/postgres.sql kanboard
|
||||
|
|
|
|||
15
README.md
15
README.md
|
|
@ -1,10 +1,8 @@
|
|||
Kanboard
|
||||
========
|
||||
|
||||
[](https://travis-ci.org/fguillot/kanboard)
|
||||
[](https://scrutinizer-ci.com/g/fguillot/kanboard/)
|
||||
[](https://insight.sensiolabs.com/projects/5e50750e-fc62-4a1f-b02a-71991123a2a7)
|
||||
[](https://gitter.im/kanboard/kanboard)
|
||||
[](https://travis-ci.org/kanboard/kanboard)
|
||||
[](https://scrutinizer-ci.com/g/kanboard/kanboard/?branch=master)
|
||||
|
||||
Kanboard is a project management software that focus on the Kanban methodology.
|
||||
|
||||
|
|
@ -15,16 +13,17 @@ Official website: <https://kanboard.net>
|
|||
- Open source and self-hosted
|
||||
- Super simple installation
|
||||
- Translated in many languages
|
||||
- Distributed under [MIT License](https://github.com/fguillot/kanboard/blob/master/LICENSE)
|
||||
- Distributed under [MIT License](https://github.com/kanboard/kanboard/blob/master/LICENSE)
|
||||
- The complete [list of features are available on the website](https://kanboard.net/features)
|
||||
- [Change Log](https://github.com/fguillot/kanboard/blob/master/ChangeLog)
|
||||
- [Documentation](https://github.com/fguillot/kanboard/blob/master/doc/index.markdown)
|
||||
- [Change Log](https://github.com/kanboard/kanboard/blob/master/ChangeLog)
|
||||
- [Documentation](https://github.com/kanboard/kanboard/blob/master/doc/index.markdown)
|
||||
- IRC channel: [#kanboard](ircs://chat.freenode.net:6697/#kanboard) (Freenode)
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
- Main developer: [Frédéric Guillot](https://github.com/fguillot)
|
||||
- [List of contributors](https://github.com/fguillot/kanboard/blob/master/CONTRIBUTORS.md)
|
||||
- [List of contributors](https://github.com/kanboard/kanboard/blob/master/CONTRIBUTORS.md)
|
||||
|
||||
Installation and Upgrade
|
||||
------------------------
|
||||
|
|
|
|||
2
app.json
2
app.json
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "Kanboard",
|
||||
"description": "Kanboard is a simple visual task board",
|
||||
"repository": "https://github.com/fguillot/kanboard",
|
||||
"repository": "https://github.com/kanboard/kanboard",
|
||||
"logo": "https://kanboard.net/assets/img/icon.svg",
|
||||
"keywords": ["kanboard", "kanban", "php", "agile"],
|
||||
"addons": ["heroku-postgresql:hobby-dev"]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Event\GenericEvent;
|
|||
/**
|
||||
* Base class for automatic actions
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class Base extends \Kanboard\Core\Base
|
||||
|
|
@ -216,7 +216,8 @@ abstract class Base extends \Kanboard\Core\Base
|
|||
*/
|
||||
public function hasRequiredProject(array $data)
|
||||
{
|
||||
return isset($data['project_id']) && $data['project_id'] == $this->getProjectId();
|
||||
return (isset($data['project_id']) && $data['project_id'] == $this->getProjectId()) ||
|
||||
(isset($data['task']['project_id']) && $data['task']['project_id'] == $this->getProjectId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -226,10 +227,14 @@ abstract class Base extends \Kanboard\Core\Base
|
|||
* @param array $data Event data dictionary
|
||||
* @return bool True if all keys are there
|
||||
*/
|
||||
public function hasRequiredParameters(array $data)
|
||||
public function hasRequiredParameters(array $data, array $parameters = array())
|
||||
{
|
||||
foreach ($this->getEventRequiredParameters() as $parameter) {
|
||||
if (! isset($data[$parameter])) {
|
||||
$parameters = $parameters ?: $this->getEventRequiredParameters();
|
||||
|
||||
foreach ($parameters as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
return isset($data[$key]) && $this->hasRequiredParameters($data[$key], $value);
|
||||
} else if (! isset($data[$value])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Kanboard\Action;
|
|||
/**
|
||||
* Create automatically a comment from a webhook
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class CommentCreation extends Base
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Add a comment of the triggering event to the task description.
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Oren Ben-Kiki
|
||||
*/
|
||||
class CommentCreationMoveTaskColumn extends Base
|
||||
|
|
@ -55,7 +55,13 @@ class CommentCreationMoveTaskColumn extends Base
|
|||
*/
|
||||
public function getEventRequiredParameters()
|
||||
{
|
||||
return array('task_id', 'column_id');
|
||||
return array(
|
||||
'task_id',
|
||||
'task' => array(
|
||||
'column_id',
|
||||
'project_id',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,7 +77,7 @@ class CommentCreationMoveTaskColumn extends Base
|
|||
return false;
|
||||
}
|
||||
|
||||
$column = $this->columnModel->getById($data['column_id']);
|
||||
$column = $this->columnModel->getById($data['task']['column_id']);
|
||||
|
||||
return (bool) $this->commentModel->create(array(
|
||||
'comment' => t('Moved to column %s', $column['title']),
|
||||
|
|
@ -89,6 +95,6 @@ class CommentCreationMoveTaskColumn extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('column_id');
|
||||
return $data['task']['column_id'] == $this->getParam('column_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Set a category automatically according to the color
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignCategoryColor extends Base
|
||||
|
|
@ -60,7 +60,10 @@ class TaskAssignCategoryColor extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'color_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'color_id',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -90,6 +93,6 @@ class TaskAssignCategoryColor extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['color_id'] == $this->getParam('color_id');
|
||||
return $data['task']['color_id'] == $this->getParam('color_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Kanboard\Action;
|
|||
/**
|
||||
* Set a category automatically according to a label
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignCategoryLabel extends Base
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskLinkModel;
|
|||
/**
|
||||
* Set a category automatically according to a task link
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Olivier Maridat
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
|
|
@ -60,8 +60,10 @@ class TaskAssignCategoryLink extends Base
|
|||
public function getEventRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'link_id',
|
||||
'task_link' => array(
|
||||
'task_id',
|
||||
'link_id',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +77,7 @@ class TaskAssignCategoryLink extends Base
|
|||
public function doAction(array $data)
|
||||
{
|
||||
$values = array(
|
||||
'id' => $data['task_id'],
|
||||
'id' => $data['task_link']['task_id'],
|
||||
'category_id' => $this->getParam('category_id'),
|
||||
);
|
||||
|
||||
|
|
@ -91,9 +93,8 @@ class TaskAssignCategoryLink extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
if ($data['link_id'] == $this->getParam('link_id')) {
|
||||
$task = $this->taskFinderModel->getById($data['task_id']);
|
||||
return empty($task['category_id']);
|
||||
if ($data['task_link']['link_id'] == $this->getParam('link_id')) {
|
||||
return empty($data['task']['category_id']);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Assign a color to a specific category
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignColorCategory extends Base
|
||||
|
|
@ -60,7 +60,10 @@ class TaskAssignColorCategory extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'category_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'category_id',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -90,6 +93,6 @@ class TaskAssignColorCategory extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['category_id'] == $this->getParam('category_id');
|
||||
return $data['task']['category_id'] == $this->getParam('category_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Assign a color to a task
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignColorColumn extends Base
|
||||
|
|
@ -61,7 +61,10 @@ class TaskAssignColorColumn extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'column_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -91,6 +94,6 @@ class TaskAssignColorColumn extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('column_id');
|
||||
return $data['task']['column_id'] == $this->getParam('column_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskLinkModel;
|
|||
/**
|
||||
* Assign a color to a specific task link
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignColorLink extends Base
|
||||
|
|
@ -59,8 +59,10 @@ class TaskAssignColorLink extends Base
|
|||
public function getEventRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'link_id',
|
||||
'task_link' => array(
|
||||
'task_id',
|
||||
'link_id',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +76,7 @@ class TaskAssignColorLink extends Base
|
|||
public function doAction(array $data)
|
||||
{
|
||||
$values = array(
|
||||
'id' => $data['task_id'],
|
||||
'id' => $data['task_link']['task_id'],
|
||||
'color_id' => $this->getParam('color_id'),
|
||||
);
|
||||
|
||||
|
|
@ -90,6 +92,6 @@ class TaskAssignColorLink extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['link_id'] == $this->getParam('link_id');
|
||||
return $data['task_link']['link_id'] == $this->getParam('link_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Assign a color to a priority
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignColorPriority extends Base
|
||||
|
|
@ -60,7 +60,10 @@ class TaskAssignColorPriority extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'priority',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'priority',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -90,6 +93,6 @@ class TaskAssignColorPriority extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['priority'] == $this->getParam('priority');
|
||||
return $data['task']['priority'] == $this->getParam('priority');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Assign a color to a specific user
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignColorUser extends Base
|
||||
|
|
@ -61,7 +61,10 @@ class TaskAssignColorUser extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'owner_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'owner_id',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -91,6 +94,6 @@ class TaskAssignColorUser extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['owner_id'] == $this->getParam('user_id');
|
||||
return $data['task']['owner_id'] == $this->getParam('user_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Assign a task to the logged user
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignCurrentUser extends Base
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Assign a task to the logged user on column change
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignCurrentUserColumn extends Base
|
||||
|
|
@ -59,7 +59,10 @@ class TaskAssignCurrentUserColumn extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'column_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -93,6 +96,6 @@ class TaskAssignCurrentUserColumn extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('column_id');
|
||||
return $data['task']['column_id'] == $this->getParam('column_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Action;
|
||||
|
||||
use Kanboard\Model\TaskModel;
|
||||
|
||||
/**
|
||||
* Set the due date of task
|
||||
*
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignDueDateOnCreation extends Base
|
||||
{
|
||||
/**
|
||||
* Get automatic action description
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return t('Automatically set the due date on task creation');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of compatible events
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getCompatibleEvents()
|
||||
{
|
||||
return array(
|
||||
TaskModel::EVENT_CREATE,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required parameter for the action (defined by the user)
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getActionRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'duration' => t('Duration in days')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required parameter for the event
|
||||
*
|
||||
* @access public
|
||||
* @return string[]
|
||||
*/
|
||||
public function getEventRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action (set the task color)
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
$values = array(
|
||||
'id' => $data['task_id'],
|
||||
'date_due' => strtotime('+'.$this->getParam('duration').'days'),
|
||||
);
|
||||
|
||||
return $this->taskModificationModel->update($values, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the event data meet the action condition
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Assign a task to a specific user
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignSpecificUser extends Base
|
||||
|
|
@ -61,7 +61,10 @@ class TaskAssignSpecificUser extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'column_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -91,6 +94,6 @@ class TaskAssignSpecificUser extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('column_id');
|
||||
return $data['task']['column_id'] == $this->getParam('column_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Kanboard\Action;
|
|||
/**
|
||||
* Assign a task to someone
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Actionv
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAssignUser extends Base
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Kanboard\Action;
|
|||
/**
|
||||
* Close automatically a task
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskClose extends Base
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Close automatically a task in a specific column
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskCloseColumn extends Base
|
||||
|
|
@ -55,7 +55,13 @@ class TaskCloseColumn extends Base
|
|||
*/
|
||||
public function getEventRequiredParameters()
|
||||
{
|
||||
return array('task_id', 'column_id');
|
||||
return array(
|
||||
'task_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -79,6 +85,6 @@ class TaskCloseColumn extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('column_id');
|
||||
return $data['task']['column_id'] == $this->getParam('column_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Close automatically a task after when inactive
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskCloseNoActivity extends Base
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Action;
|
||||
|
||||
use Kanboard\Model\TaskModel;
|
||||
|
||||
/**
|
||||
* Close automatically a task after inactive and in an defined column
|
||||
*
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskCloseNoActivityColumn extends Base
|
||||
{
|
||||
/**
|
||||
* Get automatic action description
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return t('Close a task when there is no activity in an specific column');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of compatible events
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getCompatibleEvents()
|
||||
{
|
||||
return array(TaskModel::EVENT_DAILY_CRONJOB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required parameter for the action (defined by the user)
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getActionRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'duration' => t('Duration in days'),
|
||||
'column_id' => t('Column')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required parameter for the event
|
||||
*
|
||||
* @access public
|
||||
* @return string[]
|
||||
*/
|
||||
public function getEventRequiredParameters()
|
||||
{
|
||||
return array('tasks');
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action (close the task)
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
$results = array();
|
||||
$max = $this->getParam('duration') * 86400;
|
||||
|
||||
foreach ($data['tasks'] as $task) {
|
||||
$duration = time() - $task['date_modification'];
|
||||
|
||||
if ($duration > $max && $task['column_id'] == $this->getParam('column_id')) {
|
||||
$results[] = $this->taskStatusModel->close($task['id']);
|
||||
}
|
||||
}
|
||||
|
||||
return in_array(true, $results, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the event data meet the action condition
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return count($data['tasks']) > 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ namespace Kanboard\Action;
|
|||
/**
|
||||
* Create automatically a task from a webhook
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskCreation extends Base
|
||||
|
|
@ -52,6 +52,7 @@ class TaskCreation extends Base
|
|||
public function getEventRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'project_id',
|
||||
'reference',
|
||||
'title',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Duplicate a task to another project
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskDuplicateAnotherProject extends Base
|
||||
|
|
@ -62,7 +62,10 @@ class TaskDuplicateAnotherProject extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'column_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +79,12 @@ class TaskDuplicateAnotherProject extends Base
|
|||
public function doAction(array $data)
|
||||
{
|
||||
$destination_column_id = $this->columnModel->getFirstColumnId($this->getParam('project_id'));
|
||||
return (bool) $this->taskDuplicationModel->duplicateToProject($data['task_id'], $this->getParam('project_id'), null, $destination_column_id);
|
||||
return (bool) $this->taskProjectDuplicationModel->duplicateToProject(
|
||||
$data['task_id'],
|
||||
$this->getParam('project_id'),
|
||||
null,
|
||||
$destination_column_id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -88,6 +96,6 @@ class TaskDuplicateAnotherProject extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('column_id') && $data['project_id'] != $this->getParam('project_id');
|
||||
return $data['task']['column_id'] == $this->getParam('column_id') && $data['task']['project_id'] != $this->getParam('project_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Email a task to someone
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskEmail extends Base
|
||||
|
|
@ -62,7 +62,10 @@ class TaskEmail extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'column_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -78,13 +81,14 @@ class TaskEmail extends Base
|
|||
$user = $this->userModel->getById($this->getParam('user_id'));
|
||||
|
||||
if (! empty($user['email'])) {
|
||||
$task = $this->taskFinderModel->getDetails($data['task_id']);
|
||||
|
||||
$this->emailClient->send(
|
||||
$user['email'],
|
||||
$user['name'] ?: $user['username'],
|
||||
$this->getParam('subject'),
|
||||
$this->template->render('notification/task_create', array('task' => $task, 'application_url' => $this->configModel->get('application_url')))
|
||||
$this->template->render('notification/task_create', array(
|
||||
'task' => $data['task'],
|
||||
'application_url' => $this->configModel->get('application_url'),
|
||||
))
|
||||
);
|
||||
|
||||
return true;
|
||||
|
|
@ -102,6 +106,6 @@ class TaskEmail extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('column_id');
|
||||
return $data['task']['column_id'] == $this->getParam('column_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Email a task with no activity
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskEmailNoActivity extends Base
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Move a task to another project
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskMoveAnotherProject extends Base
|
||||
|
|
@ -61,8 +61,10 @@ class TaskMoveAnotherProject extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'column_id',
|
||||
'project_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +77,7 @@ class TaskMoveAnotherProject extends Base
|
|||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
return $this->taskDuplicationModel->moveToProject($data['task_id'], $this->getParam('project_id'));
|
||||
return $this->taskProjectMoveModel->moveToProject($data['task_id'], $this->getParam('project_id'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -87,6 +89,6 @@ class TaskMoveAnotherProject extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('column_id') && $data['project_id'] != $this->getParam('project_id');
|
||||
return $data['task']['column_id'] == $this->getParam('column_id') && $data['task']['project_id'] != $this->getParam('project_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Move a task to another column when an assignee is set
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Francois Ferrand
|
||||
*/
|
||||
class TaskMoveColumnAssigned extends Base
|
||||
|
|
@ -61,8 +61,13 @@ class TaskMoveColumnAssigned extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'column_id',
|
||||
'owner_id'
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
'owner_id',
|
||||
'position',
|
||||
'swimlane_id',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -75,14 +80,12 @@ class TaskMoveColumnAssigned extends Base
|
|||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
$original_task = $this->taskFinderModel->getById($data['task_id']);
|
||||
|
||||
return $this->taskPositionModel->movePosition(
|
||||
$data['project_id'],
|
||||
$data['task']['project_id'],
|
||||
$data['task_id'],
|
||||
$this->getParam('dest_column_id'),
|
||||
$original_task['position'],
|
||||
$original_task['swimlane_id'],
|
||||
$data['task']['position'],
|
||||
$data['task']['swimlane_id'],
|
||||
false
|
||||
);
|
||||
}
|
||||
|
|
@ -96,6 +99,6 @@ class TaskMoveColumnAssigned extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('src_column_id') && $data['owner_id'] > 0;
|
||||
return $data['task']['column_id'] == $this->getParam('src_column_id') && $data['task']['owner_id'] > 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Move a task to another column when the category is changed
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Francois Ferrand
|
||||
*/
|
||||
class TaskMoveColumnCategoryChange extends Base
|
||||
|
|
@ -60,8 +60,13 @@ class TaskMoveColumnCategoryChange extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'column_id',
|
||||
'category_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
'category_id',
|
||||
'position',
|
||||
'swimlane_id',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -74,14 +79,12 @@ class TaskMoveColumnCategoryChange extends Base
|
|||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
$original_task = $this->taskFinderModel->getById($data['task_id']);
|
||||
|
||||
return $this->taskPositionModel->movePosition(
|
||||
$data['project_id'],
|
||||
$data['task']['project_id'],
|
||||
$data['task_id'],
|
||||
$this->getParam('dest_column_id'),
|
||||
$original_task['position'],
|
||||
$original_task['swimlane_id'],
|
||||
$data['task']['position'],
|
||||
$data['task']['swimlane_id'],
|
||||
false
|
||||
);
|
||||
}
|
||||
|
|
@ -95,6 +98,6 @@ class TaskMoveColumnCategoryChange extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] != $this->getParam('dest_column_id') && $data['category_id'] == $this->getParam('category_id');
|
||||
return $data['task']['column_id'] != $this->getParam('dest_column_id') && $data['task']['category_id'] == $this->getParam('category_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Action;
|
||||
|
||||
use Kanboard\Model\TaskModel;
|
||||
|
||||
/**
|
||||
* Move a task to another column when the task is closed
|
||||
*
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskMoveColumnClosed extends Base
|
||||
{
|
||||
/**
|
||||
* Get automatic action description
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return t('Move the task to another column when closed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of compatible events
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getCompatibleEvents()
|
||||
{
|
||||
return array(
|
||||
TaskModel::EVENT_CLOSE,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required parameter for the action (defined by the user)
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getActionRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'dest_column_id' => t('Destination column'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required parameter for the event
|
||||
*
|
||||
* @access public
|
||||
* @return string[]
|
||||
*/
|
||||
public function getEventRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
'swimlane_id',
|
||||
'is_active',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action (move the task to another column)
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
return $this->taskPositionModel->movePosition(
|
||||
$data['task']['project_id'],
|
||||
$data['task']['id'],
|
||||
$this->getParam('dest_column_id'),
|
||||
1,
|
||||
$data['task']['swimlane_id'],
|
||||
false,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the event data meet the action condition
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['task']['column_id'] != $this->getParam('dest_column_id') && $data['task']['is_active'] == 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Action;
|
||||
|
||||
use Kanboard\Model\TaskModel;
|
||||
|
||||
/**
|
||||
* Move a task to another column when not moved during a given period
|
||||
*
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskMoveColumnNotMovedPeriod extends Base
|
||||
{
|
||||
/**
|
||||
* Get automatic action description
|
||||
*
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return t('Move the task to another column when not moved during a given period');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of compatible events
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getCompatibleEvents()
|
||||
{
|
||||
return array(TaskModel::EVENT_DAILY_CRONJOB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required parameter for the action (defined by the user)
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function getActionRequiredParameters()
|
||||
{
|
||||
return array(
|
||||
'duration' => t('Duration in days'),
|
||||
'src_column_id' => t('Source column'),
|
||||
'dest_column_id' => t('Destination column'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the required parameter for the event
|
||||
*
|
||||
* @access public
|
||||
* @return string[]
|
||||
*/
|
||||
public function getEventRequiredParameters()
|
||||
{
|
||||
return array('tasks');
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the action (close the task)
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool True if the action was executed or false when not executed
|
||||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
$results = array();
|
||||
$max = $this->getParam('duration') * 86400;
|
||||
|
||||
foreach ($data['tasks'] as $task) {
|
||||
$duration = time() - $task['date_moved'];
|
||||
|
||||
if ($duration > $max && $task['column_id'] == $this->getParam('src_column_id')) {
|
||||
$results[] = $this->taskPositionModel->movePosition(
|
||||
$task['project_id'],
|
||||
$task['id'],
|
||||
$this->getParam('dest_column_id'),
|
||||
1,
|
||||
$task['swimlane_id'],
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return in_array(true, $results, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the event data meet the action condition
|
||||
*
|
||||
* @access public
|
||||
* @param array $data Event data dictionary
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return count($data['tasks']) > 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Move a task to another column when an assignee is cleared
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Francois Ferrand
|
||||
*/
|
||||
class TaskMoveColumnUnAssigned extends Base
|
||||
|
|
@ -61,8 +61,13 @@ class TaskMoveColumnUnAssigned extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'column_id',
|
||||
'owner_id'
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
'owner_id',
|
||||
'position',
|
||||
'swimlane_id',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -75,14 +80,12 @@ class TaskMoveColumnUnAssigned extends Base
|
|||
*/
|
||||
public function doAction(array $data)
|
||||
{
|
||||
$original_task = $this->taskFinderModel->getById($data['task_id']);
|
||||
|
||||
return $this->taskPositionModel->movePosition(
|
||||
$data['project_id'],
|
||||
$data['task']['project_id'],
|
||||
$data['task_id'],
|
||||
$this->getParam('dest_column_id'),
|
||||
$original_task['position'],
|
||||
$original_task['swimlane_id'],
|
||||
$data['task']['position'],
|
||||
$data['task']['swimlane_id'],
|
||||
false
|
||||
);
|
||||
}
|
||||
|
|
@ -96,6 +99,6 @@ class TaskMoveColumnUnAssigned extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('src_column_id') && $data['owner_id'] == 0;
|
||||
return $data['task']['column_id'] == $this->getParam('src_column_id') && $data['task']['owner_id'] == 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace Kanboard\Action;
|
|||
/**
|
||||
* Open automatically a task
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskOpen extends Base
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Kanboard\Model\TaskModel;
|
|||
/**
|
||||
* Set the start date of task
|
||||
*
|
||||
* @package action
|
||||
* @package Kanboard\Action
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskUpdateStartDate extends Base
|
||||
|
|
@ -59,7 +59,10 @@ class TaskUpdateStartDate extends Base
|
|||
{
|
||||
return array(
|
||||
'task_id',
|
||||
'column_id',
|
||||
'task' => array(
|
||||
'project_id',
|
||||
'column_id',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -89,6 +92,6 @@ class TaskUpdateStartDate extends Base
|
|||
*/
|
||||
public function hasRequiredCondition(array $data)
|
||||
{
|
||||
return $data['column_id'] == $this->getParam('column_id');
|
||||
return $data['task']['column_id'] == $this->getParam('column_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
/**
|
||||
* Class ActionAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ActionAuthorization extends ProjectAuthorization
|
||||
{
|
||||
public function check($class, $method, $action_id)
|
||||
{
|
||||
if ($this->userSession->isLogged()) {
|
||||
$this->checkProjectPermission($class, $method, $this->actionModel->getProjectId($action_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
/**
|
||||
* Class CategoryAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class CategoryAuthorization extends ProjectAuthorization
|
||||
{
|
||||
public function check($class, $method, $category_id)
|
||||
{
|
||||
if ($this->userSession->isLogged()) {
|
||||
$this->checkProjectPermission($class, $method, $this->categoryModel->getProjectId($category_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
/**
|
||||
* Class ColumnAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ColumnAuthorization extends ProjectAuthorization
|
||||
{
|
||||
public function check($class, $method, $column_id)
|
||||
{
|
||||
if ($this->userSession->isLogged()) {
|
||||
$this->checkProjectPermission($class, $method, $this->columnModel->getProjectId($column_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
/**
|
||||
* Class CommentAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class CommentAuthorization extends ProjectAuthorization
|
||||
{
|
||||
public function check($class, $method, $comment_id)
|
||||
{
|
||||
if ($this->userSession->isLogged()) {
|
||||
$this->checkProjectPermission($class, $method, $this->commentModel->getProjectId($comment_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
use JsonRPC\Exception\AccessDeniedException;
|
||||
use Kanboard\Core\Base;
|
||||
|
||||
/**
|
||||
* Class ProcedureAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ProcedureAuthorization extends Base
|
||||
{
|
||||
private $userSpecificProcedures = array(
|
||||
'getMe',
|
||||
'getMyDashboard',
|
||||
'getMyActivityStream',
|
||||
'createMyPrivateProject',
|
||||
'getMyProjectsList',
|
||||
'getMyProjects',
|
||||
'getMyOverdueTasks',
|
||||
);
|
||||
|
||||
public function check($procedure)
|
||||
{
|
||||
if (! $this->userSession->isLogged() && in_array($procedure, $this->userSpecificProcedures)) {
|
||||
throw new AccessDeniedException('This procedure is not available with the API credentials');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
use JsonRPC\Exception\AccessDeniedException;
|
||||
use Kanboard\Core\Base;
|
||||
|
||||
/**
|
||||
* Class ProjectAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ProjectAuthorization extends Base
|
||||
{
|
||||
public function check($class, $method, $project_id)
|
||||
{
|
||||
if ($this->userSession->isLogged()) {
|
||||
$this->checkProjectPermission($class, $method, $project_id);
|
||||
}
|
||||
}
|
||||
|
||||
protected function checkProjectPermission($class, $method, $project_id)
|
||||
{
|
||||
if (empty($project_id)) {
|
||||
throw new AccessDeniedException('Project not found');
|
||||
}
|
||||
|
||||
$role = $this->projectUserRoleModel->getUserRole($project_id, $this->userSession->getId());
|
||||
|
||||
if (! $this->apiProjectAuthorization->isAllowed($class, $method, $role)) {
|
||||
throw new AccessDeniedException('Project access denied');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
/**
|
||||
* Class SubtaskAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class SubtaskAuthorization extends ProjectAuthorization
|
||||
{
|
||||
public function check($class, $method, $subtask_id)
|
||||
{
|
||||
if ($this->userSession->isLogged()) {
|
||||
$this->checkProjectPermission($class, $method, $this->subtaskModel->getProjectId($subtask_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
/**
|
||||
* Class TaskAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskAuthorization extends ProjectAuthorization
|
||||
{
|
||||
public function check($class, $method, $category_id)
|
||||
{
|
||||
if ($this->userSession->isLogged()) {
|
||||
$this->checkProjectPermission($class, $method, $this->taskFinderModel->getProjectId($category_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
/**
|
||||
* Class TaskFileAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskFileAuthorization extends ProjectAuthorization
|
||||
{
|
||||
public function check($class, $method, $file_id)
|
||||
{
|
||||
if ($this->userSession->isLogged()) {
|
||||
$this->checkProjectPermission($class, $method, $this->taskFileModel->getProjectId($file_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
/**
|
||||
* Class TaskLinkAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskLinkAuthorization extends ProjectAuthorization
|
||||
{
|
||||
public function check($class, $method, $task_link_id)
|
||||
{
|
||||
if ($this->userSession->isLogged()) {
|
||||
$this->checkProjectPermission($class, $method, $this->taskLinkModel->getProjectId($task_link_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Authorization;
|
||||
|
||||
use JsonRPC\Exception\AccessDeniedException;
|
||||
use Kanboard\Core\Base;
|
||||
|
||||
/**
|
||||
* Class UserAuthorization
|
||||
*
|
||||
* @package Kanboard\Api\Authorization
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class UserAuthorization extends Base
|
||||
{
|
||||
public function check($class, $method)
|
||||
{
|
||||
if ($this->userSession->isLogged() && ! $this->apiAuthorization->isAllowed($class, $method, $this->userSession->getRole())) {
|
||||
throw new AccessDeniedException('You are not allowed to access to this resource');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
|
||||
/**
|
||||
* Board API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class BoardApi extends BaseApi
|
||||
{
|
||||
public function getBoard($project_id)
|
||||
{
|
||||
$this->checkProjectPermission($project_id);
|
||||
return $this->boardModel->getBoard($project_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -13,46 +13,8 @@ use Kanboard\Core\Base;
|
|||
* @package Kanboard\Api\Middleware
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class AuthenticationApiMiddleware extends Base implements MiddlewareInterface
|
||||
class AuthenticationMiddleware extends Base implements MiddlewareInterface
|
||||
{
|
||||
private $user_allowed_procedures = array(
|
||||
'getMe',
|
||||
'getMyDashboard',
|
||||
'getMyActivityStream',
|
||||
'createMyPrivateProject',
|
||||
'getMyProjectsList',
|
||||
'getMyProjects',
|
||||
'getMyOverdueTasks',
|
||||
);
|
||||
|
||||
private $both_allowed_procedures = array(
|
||||
'getTimezone',
|
||||
'getVersion',
|
||||
'getDefaultTaskColor',
|
||||
'getDefaultTaskColors',
|
||||
'getColorList',
|
||||
'getProjectById',
|
||||
'getSubTask',
|
||||
'getTask',
|
||||
'getTaskByReference',
|
||||
'getTimeSpent',
|
||||
'getAllTasks',
|
||||
'getAllSubTasks',
|
||||
'hasTimer',
|
||||
'logStartTime',
|
||||
'logEndTime',
|
||||
'openTask',
|
||||
'closeTask',
|
||||
'moveTaskPosition',
|
||||
'createTask',
|
||||
'createSubtask',
|
||||
'updateTask',
|
||||
'getBoard',
|
||||
'getProjectActivity',
|
||||
'getOverdueTasksByProject',
|
||||
'searchTasks',
|
||||
);
|
||||
|
||||
/**
|
||||
* Execute Middleware
|
||||
*
|
||||
|
|
@ -68,11 +30,8 @@ class AuthenticationApiMiddleware extends Base implements MiddlewareInterface
|
|||
$this->dispatcher->dispatch('app.bootstrap');
|
||||
|
||||
if ($this->isUserAuthenticated($username, $password)) {
|
||||
$this->checkProcedurePermission(true, $procedureName);
|
||||
$this->userSession->initialize($this->userModel->getByUsername($username));
|
||||
} elseif ($this->isAppAuthenticated($username, $password)) {
|
||||
$this->checkProcedurePermission(false, $procedureName);
|
||||
} else {
|
||||
} elseif (! $this->isAppAuthenticated($username, $password)) {
|
||||
$this->logger->error('API authentication failure for '.$username);
|
||||
throw new AuthenticationFailureException('Wrong credentials');
|
||||
}
|
||||
|
|
@ -120,18 +79,4 @@ class AuthenticationApiMiddleware extends Base implements MiddlewareInterface
|
|||
|
||||
return $this->configModel->get('api_token');
|
||||
}
|
||||
|
||||
public function checkProcedurePermission($is_user, $procedure)
|
||||
{
|
||||
$is_both_procedure = in_array($procedure, $this->both_allowed_procedures);
|
||||
$is_user_procedure = in_array($procedure, $this->user_allowed_procedures);
|
||||
|
||||
if ($is_user && ! $is_both_procedure && ! $is_user_procedure) {
|
||||
throw new AccessDeniedException('Permission denied');
|
||||
} elseif (! $is_user && ! $is_both_procedure && $is_user_procedure) {
|
||||
throw new AccessDeniedException('Permission denied');
|
||||
}
|
||||
|
||||
$this->logger->debug('API call: '.$procedure);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
use Kanboard\Api\Authorization\ActionAuthorization;
|
||||
use Kanboard\Api\Authorization\ProjectAuthorization;
|
||||
|
||||
/**
|
||||
* Action API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ActionApi extends Base
|
||||
class ActionProcedure extends BaseProcedure
|
||||
{
|
||||
public function getAvailableActions()
|
||||
{
|
||||
|
|
@ -29,16 +30,19 @@ class ActionApi extends Base
|
|||
|
||||
public function removeAction($action_id)
|
||||
{
|
||||
ActionAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeAction', $action_id);
|
||||
return $this->actionModel->remove($action_id);
|
||||
}
|
||||
|
||||
public function getActions($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getActions', $project_id);
|
||||
return $this->actionModel->getAllByProject($project_id);
|
||||
}
|
||||
|
||||
public function createAction($project_id, $event_name, $action_name, array $params)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createAction', $project_id);
|
||||
$values = array(
|
||||
'project_id' => $project_id,
|
||||
'event_name' => $event_name,
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
/**
|
||||
* App API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class AppApi extends Base
|
||||
class AppProcedure extends BaseProcedure
|
||||
{
|
||||
public function getTimezone()
|
||||
{
|
||||
|
|
@ -1,30 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use JsonRPC\Exception\AccessDeniedException;
|
||||
use Kanboard\Api\Authorization\ProcedureAuthorization;
|
||||
use Kanboard\Api\Authorization\UserAuthorization;
|
||||
use Kanboard\Core\Base;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
abstract class BaseApi extends Base
|
||||
abstract class BaseProcedure extends Base
|
||||
{
|
||||
public function checkProjectPermission($project_id)
|
||||
public function beforeProcedure($procedure)
|
||||
{
|
||||
if ($this->userSession->isLogged() && ! $this->projectPermissionModel->isUserAllowed($project_id, $this->userSession->getId())) {
|
||||
throw new AccessDeniedException('Permission denied');
|
||||
}
|
||||
}
|
||||
|
||||
public function checkTaskPermission($task_id)
|
||||
{
|
||||
if ($this->userSession->isLogged()) {
|
||||
$this->checkProjectPermission($this->taskFinderModel->getProjectId($task_id));
|
||||
}
|
||||
ProcedureAuthorization::getInstance($this->container)->check($procedure);
|
||||
UserAuthorization::getInstance($this->container)->check($this->getClassName(), $procedure);
|
||||
}
|
||||
|
||||
protected function formatTask($task)
|
||||
|
|
@ -71,4 +65,21 @@ abstract class BaseApi extends Base
|
|||
|
||||
return $projects;
|
||||
}
|
||||
|
||||
protected function filterValues(array $values)
|
||||
{
|
||||
foreach ($values as $key => $value) {
|
||||
if (is_null($value)) {
|
||||
unset($values[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
protected function getClassName()
|
||||
{
|
||||
$reflection = new ReflectionClass(get_called_class());
|
||||
return $reflection->getShortName();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Api\Authorization\ProjectAuthorization;
|
||||
use Kanboard\Formatter\BoardFormatter;
|
||||
|
||||
/**
|
||||
* Board API controller
|
||||
*
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class BoardProcedure extends BaseProcedure
|
||||
{
|
||||
public function getBoard($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getBoard', $project_id);
|
||||
|
||||
return BoardFormatter::getInstance($this->container)
|
||||
->withProjectId($project_id)
|
||||
->withQuery($this->taskFinderModel->getExtendedQuery())
|
||||
->format();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
use Kanboard\Api\Authorization\CategoryAuthorization;
|
||||
use Kanboard\Api\Authorization\ProjectAuthorization;
|
||||
|
||||
/**
|
||||
* Category API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class CategoryApi extends Base
|
||||
class CategoryProcedure extends BaseProcedure
|
||||
{
|
||||
public function getCategory($category_id)
|
||||
{
|
||||
CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'getCategory', $category_id);
|
||||
return $this->categoryModel->getById($category_id);
|
||||
}
|
||||
|
||||
public function getAllCategories($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllCategories', $project_id);
|
||||
return $this->categoryModel->getAll($project_id);
|
||||
}
|
||||
|
||||
public function removeCategory($category_id)
|
||||
{
|
||||
CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeCategory', $category_id);
|
||||
return $this->categoryModel->remove($category_id);
|
||||
}
|
||||
|
||||
public function createCategory($project_id, $name)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createCategory', $project_id);
|
||||
|
||||
$values = array(
|
||||
'project_id' => $project_id,
|
||||
'name' => $name,
|
||||
|
|
@ -40,6 +46,8 @@ class CategoryApi extends Base
|
|||
|
||||
public function updateCategory($id, $name)
|
||||
{
|
||||
CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateCategory', $id);
|
||||
|
||||
$values = array(
|
||||
'id' => $id,
|
||||
'name' => $name,
|
||||
|
|
@ -1,42 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Api\Authorization\ColumnAuthorization;
|
||||
use Kanboard\Api\Authorization\ProjectAuthorization;
|
||||
|
||||
/**
|
||||
* Column API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ColumnApi extends BaseApi
|
||||
class ColumnProcedure extends BaseProcedure
|
||||
{
|
||||
public function getColumns($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getColumns', $project_id);
|
||||
return $this->columnModel->getAll($project_id);
|
||||
}
|
||||
|
||||
public function getColumn($column_id)
|
||||
{
|
||||
ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'getColumn', $column_id);
|
||||
return $this->columnModel->getById($column_id);
|
||||
}
|
||||
|
||||
public function updateColumn($column_id, $title, $task_limit = 0, $description = '')
|
||||
{
|
||||
ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateColumn', $column_id);
|
||||
return $this->columnModel->update($column_id, $title, $task_limit, $description);
|
||||
}
|
||||
|
||||
public function addColumn($project_id, $title, $task_limit = 0, $description = '')
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addColumn', $project_id);
|
||||
return $this->columnModel->create($project_id, $title, $task_limit, $description);
|
||||
}
|
||||
|
||||
public function removeColumn($column_id)
|
||||
{
|
||||
ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeColumn', $column_id);
|
||||
return $this->columnModel->remove($column_id);
|
||||
}
|
||||
|
||||
public function changeColumnPosition($project_id, $column_id, $position)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeColumnPosition', $project_id);
|
||||
return $this->columnModel->changePosition($project_id, $column_id, $position);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
use Kanboard\Api\Authorization\CommentAuthorization;
|
||||
use Kanboard\Api\Authorization\TaskAuthorization;
|
||||
|
||||
/**
|
||||
* Comment API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class CommentApi extends Base
|
||||
class CommentProcedure extends BaseProcedure
|
||||
{
|
||||
public function getComment($comment_id)
|
||||
{
|
||||
CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'getComment', $comment_id);
|
||||
return $this->commentModel->getById($comment_id);
|
||||
}
|
||||
|
||||
public function getAllComments($task_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllComments', $task_id);
|
||||
return $this->commentModel->getAll($task_id);
|
||||
}
|
||||
|
||||
public function removeComment($comment_id)
|
||||
{
|
||||
CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeComment', $comment_id);
|
||||
return $this->commentModel->remove($comment_id);
|
||||
}
|
||||
|
||||
public function createComment($task_id, $user_id, $content, $reference = '')
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createComment', $task_id);
|
||||
|
||||
$values = array(
|
||||
'task_id' => $task_id,
|
||||
'user_id' => $user_id,
|
||||
|
|
@ -43,6 +49,8 @@ class CommentApi extends Base
|
|||
|
||||
public function updateComment($id, $content)
|
||||
{
|
||||
CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateComment', $id);
|
||||
|
||||
$values = array(
|
||||
'id' => $id,
|
||||
'comment' => $content,
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
/**
|
||||
* Group Member API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class GroupMemberApi extends Base
|
||||
class GroupMemberProcedure extends BaseProcedure
|
||||
{
|
||||
public function getMemberGroups($user_id)
|
||||
{
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
/**
|
||||
* Group API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class GroupApi extends Base
|
||||
class GroupProcedure extends BaseProcedure
|
||||
{
|
||||
public function createGroup($name, $external_id = '')
|
||||
{
|
||||
|
|
@ -1,16 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
/**
|
||||
* Link API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class LinkApi extends Base
|
||||
class LinkProcedure extends BaseProcedure
|
||||
{
|
||||
/**
|
||||
* Get a link by id
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Model\SubtaskModel;
|
||||
|
||||
/**
|
||||
* Me API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class MeApi extends BaseApi
|
||||
class MeProcedure extends BaseProcedure
|
||||
{
|
||||
public function getMe()
|
||||
{
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Api\Authorization\ProjectAuthorization;
|
||||
use Kanboard\Core\ObjectStorage\ObjectStorageException;
|
||||
|
||||
/**
|
||||
* Project File API controller
|
||||
*
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ProjectFileProcedure extends BaseProcedure
|
||||
{
|
||||
public function getProjectFile($project_id, $file_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectFile', $project_id);
|
||||
return $this->projectFileModel->getById($file_id);
|
||||
}
|
||||
|
||||
public function getAllProjectFiles($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllProjectFiles', $project_id);
|
||||
return $this->projectFileModel->getAll($project_id);
|
||||
}
|
||||
|
||||
public function downloadProjectFile($project_id, $file_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'downloadProjectFile', $project_id);
|
||||
|
||||
try {
|
||||
$file = $this->projectFileModel->getById($file_id);
|
||||
|
||||
if (! empty($file)) {
|
||||
return base64_encode($this->objectStorage->get($file['path']));
|
||||
}
|
||||
} catch (ObjectStorageException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function createProjectFile($project_id, $filename, $blob)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createProjectFile', $project_id);
|
||||
|
||||
try {
|
||||
return $this->projectFileModel->uploadContent($project_id, $filename, $blob);
|
||||
} catch (ObjectStorageException $e) {
|
||||
$this->logger->error(__METHOD__.': '.$e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function removeProjectFile($project_id, $file_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProjectFile', $project_id);
|
||||
return $this->projectFileModel->remove($file_id);
|
||||
}
|
||||
|
||||
public function removeAllProjectFiles($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeAllProjectFiles', $project_id);
|
||||
return $this->projectFileModel->removeAll($project_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
use Kanboard\Api\Authorization\ProjectAuthorization;
|
||||
use Kanboard\Core\Security\Role;
|
||||
|
||||
/**
|
||||
* Project Permission API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ProjectPermissionApi extends Base
|
||||
class ProjectPermissionProcedure extends BaseProcedure
|
||||
{
|
||||
public function getProjectUsers($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectUsers', $project_id);
|
||||
return $this->projectUserRoleModel->getAllUsers($project_id);
|
||||
}
|
||||
|
||||
public function getAssignableUsers($project_id, $prepend_unassigned = false)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAssignableUsers', $project_id);
|
||||
return $this->projectUserRoleModel->getAssignableUsersList($project_id, $prepend_unassigned);
|
||||
}
|
||||
|
||||
public function addProjectUser($project_id, $user_id, $role = Role::PROJECT_MEMBER)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addProjectUser', $project_id);
|
||||
return $this->projectUserRoleModel->addUser($project_id, $user_id, $role);
|
||||
}
|
||||
|
||||
public function addProjectGroup($project_id, $group_id, $role = Role::PROJECT_MEMBER)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addProjectGroup', $project_id);
|
||||
return $this->projectGroupRoleModel->addGroup($project_id, $group_id, $role);
|
||||
}
|
||||
|
||||
public function removeProjectUser($project_id, $user_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProjectUser', $project_id);
|
||||
return $this->projectUserRoleModel->removeUser($project_id, $user_id);
|
||||
}
|
||||
|
||||
public function removeProjectGroup($project_id, $group_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProjectGroup', $project_id);
|
||||
return $this->projectGroupRoleModel->removeGroup($project_id, $group_id);
|
||||
}
|
||||
|
||||
public function changeProjectUserRole($project_id, $user_id, $role)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeProjectUserRole', $project_id);
|
||||
return $this->projectUserRoleModel->changeUserRole($project_id, $user_id, $role);
|
||||
}
|
||||
|
||||
public function changeProjectGroupRole($project_id, $group_id, $role)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeProjectGroupRole', $project_id);
|
||||
return $this->projectGroupRoleModel->changeGroupRole($project_id, $group_id, $role);
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
public function getMembers($project_id)
|
||||
public function getProjectUserRole($project_id, $user_id)
|
||||
{
|
||||
return $this->getProjectUsers($project_id);
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
public function revokeUser($project_id, $user_id)
|
||||
{
|
||||
return $this->removeProjectUser($project_id, $user_id);
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
public function allowUser($project_id, $user_id)
|
||||
{
|
||||
return $this->addProjectUser($project_id, $user_id);
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectUserRole', $project_id);
|
||||
return $this->projectUserRoleModel->getUserRole($project_id, $user_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Api\Authorization\ProjectAuthorization;
|
||||
|
||||
/**
|
||||
* Project API controller
|
||||
*
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ProjectProcedure extends BaseProcedure
|
||||
{
|
||||
public function getProjectById($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectById', $project_id);
|
||||
return $this->formatProject($this->projectModel->getById($project_id));
|
||||
}
|
||||
|
||||
public function getProjectByName($name)
|
||||
{
|
||||
$project = $this->projectModel->getByName($name);
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectByName', $project['id']);
|
||||
return $this->formatProject($project);
|
||||
}
|
||||
|
||||
public function getProjectByIdentifier($identifier)
|
||||
{
|
||||
$project = $this->formatProject($this->projectModel->getByIdentifier($identifier));
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectByIdentifier', $project['id']);
|
||||
return $this->formatProject($project);
|
||||
}
|
||||
|
||||
public function getAllProjects()
|
||||
{
|
||||
return $this->formatProjects($this->projectModel->getAll());
|
||||
}
|
||||
|
||||
public function removeProject($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProject', $project_id);
|
||||
return $this->projectModel->remove($project_id);
|
||||
}
|
||||
|
||||
public function enableProject($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableProject', $project_id);
|
||||
return $this->projectModel->enable($project_id);
|
||||
}
|
||||
|
||||
public function disableProject($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableProject', $project_id);
|
||||
return $this->projectModel->disable($project_id);
|
||||
}
|
||||
|
||||
public function enableProjectPublicAccess($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableProjectPublicAccess', $project_id);
|
||||
return $this->projectModel->enablePublicAccess($project_id);
|
||||
}
|
||||
|
||||
public function disableProjectPublicAccess($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableProjectPublicAccess', $project_id);
|
||||
return $this->projectModel->disablePublicAccess($project_id);
|
||||
}
|
||||
|
||||
public function getProjectActivities(array $project_ids)
|
||||
{
|
||||
foreach ($project_ids as $project_id) {
|
||||
ProjectAuthorization::getInstance($this->container)
|
||||
->check($this->getClassName(), 'getProjectActivities', $project_id);
|
||||
}
|
||||
|
||||
return $this->helper->projectActivity->getProjectsEvents($project_ids);
|
||||
}
|
||||
|
||||
public function getProjectActivity($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectActivity', $project_id);
|
||||
return $this->helper->projectActivity->getProjectEvents($project_id);
|
||||
}
|
||||
|
||||
public function createProject($name, $description = null, $owner_id = 0, $identifier = null)
|
||||
{
|
||||
$values = $this->filterValues(array(
|
||||
'name' => $name,
|
||||
'description' => $description,
|
||||
'identifier' => $identifier,
|
||||
));
|
||||
|
||||
list($valid, ) = $this->projectValidator->validateCreation($values);
|
||||
return $valid ? $this->projectModel->create($values, $owner_id, $this->userSession->isLogged()) : false;
|
||||
}
|
||||
|
||||
public function updateProject($project_id, $name = null, $description = null, $owner_id = null, $identifier = null)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateProject', $project_id);
|
||||
|
||||
$values = $this->filterValues(array(
|
||||
'id' => $project_id,
|
||||
'name' => $name,
|
||||
'description' => $description,
|
||||
'owner_id' => $owner_id,
|
||||
'identifier' => $identifier,
|
||||
));
|
||||
|
||||
list($valid, ) = $this->projectValidator->validateModification($values);
|
||||
return $valid && $this->projectModel->update($values);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
use Kanboard\Api\Authorization\SubtaskAuthorization;
|
||||
use Kanboard\Api\Authorization\TaskAuthorization;
|
||||
|
||||
/**
|
||||
* Subtask API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class SubtaskApi extends Base
|
||||
class SubtaskProcedure extends BaseProcedure
|
||||
{
|
||||
public function getSubtask($subtask_id)
|
||||
{
|
||||
SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSubtask', $subtask_id);
|
||||
return $this->subtaskModel->getById($subtask_id);
|
||||
}
|
||||
|
||||
public function getAllSubtasks($task_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllSubtasks', $task_id);
|
||||
return $this->subtaskModel->getAll($task_id);
|
||||
}
|
||||
|
||||
public function removeSubtask($subtask_id)
|
||||
{
|
||||
SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeSubtask', $subtask_id);
|
||||
return $this->subtaskModel->remove($subtask_id);
|
||||
}
|
||||
|
||||
public function createSubtask($task_id, $title, $user_id = 0, $time_estimated = 0, $time_spent = 0, $status = 0)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createSubtask', $task_id);
|
||||
|
||||
$values = array(
|
||||
'title' => $title,
|
||||
'task_id' => $task_id,
|
||||
|
|
@ -44,6 +50,8 @@ class SubtaskApi extends Base
|
|||
|
||||
public function updateSubtask($id, $task_id, $title = null, $user_id = null, $time_estimated = null, $time_spent = null, $status = null)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateSubtask', $task_id);
|
||||
|
||||
$values = array(
|
||||
'id' => $id,
|
||||
'task_id' => $task_id,
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Api\Authorization\SubtaskAuthorization;
|
||||
|
||||
/**
|
||||
* Subtask Time Tracking API controller
|
||||
*
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
* @author Nikolaos Georgakis
|
||||
*/
|
||||
class SubtaskTimeTrackingProcedure extends BaseProcedure
|
||||
{
|
||||
public function hasSubtaskTimer($subtask_id, $user_id)
|
||||
{
|
||||
SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'hasSubtaskTimer', $subtask_id);
|
||||
return $this->subtaskTimeTrackingModel->hasTimer($subtask_id, $user_id);
|
||||
}
|
||||
|
||||
public function setSubtaskStartTime($subtask_id, $user_id)
|
||||
{
|
||||
SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'setSubtaskStartTime', $subtask_id);
|
||||
return $this->subtaskTimeTrackingModel->logStartTime($subtask_id, $user_id);
|
||||
}
|
||||
|
||||
public function setSubtaskEndTime($subtask_id, $user_id)
|
||||
{
|
||||
SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'setSubtaskEndTime', $subtask_id);
|
||||
return $this->subtaskTimeTrackingModel->logEndTime($subtask_id, $user_id);
|
||||
}
|
||||
|
||||
public function getSubtaskTimeSpent($subtask_id, $user_id)
|
||||
{
|
||||
SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSubtaskTimeSpent', $subtask_id);
|
||||
return $this->subtaskTimeTrackingModel->getTimeSpent($subtask_id, $user_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
use Kanboard\Api\Authorization\ProjectAuthorization;
|
||||
|
||||
/**
|
||||
* Swimlane API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class SwimlaneApi extends Base
|
||||
class SwimlaneProcedure extends BaseProcedure
|
||||
{
|
||||
public function getActiveSwimlanes($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getActiveSwimlanes', $project_id);
|
||||
return $this->swimlaneModel->getSwimlanes($project_id);
|
||||
}
|
||||
|
||||
public function getAllSwimlanes($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllSwimlanes', $project_id);
|
||||
return $this->swimlaneModel->getAll($project_id);
|
||||
}
|
||||
|
||||
public function getSwimlaneById($swimlane_id)
|
||||
{
|
||||
return $this->swimlaneModel->getById($swimlane_id);
|
||||
$swimlane = $this->swimlaneModel->getById($swimlane_id);
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSwimlaneById', $swimlane['project_id']);
|
||||
return $swimlane;
|
||||
}
|
||||
|
||||
public function getSwimlaneByName($project_id, $name)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSwimlaneByName', $project_id);
|
||||
return $this->swimlaneModel->getByName($project_id, $name);
|
||||
}
|
||||
|
||||
|
|
@ -39,11 +44,13 @@ class SwimlaneApi extends Base
|
|||
|
||||
public function getDefaultSwimlane($project_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getDefaultSwimlane', $project_id);
|
||||
return $this->swimlaneModel->getDefault($project_id);
|
||||
}
|
||||
|
||||
public function addSwimlane($project_id, $name, $description = '')
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addSwimlane', $project_id);
|
||||
return $this->swimlaneModel->create(array('project_id' => $project_id, 'name' => $name, 'description' => $description));
|
||||
}
|
||||
|
||||
|
|
@ -60,21 +67,25 @@ class SwimlaneApi extends Base
|
|||
|
||||
public function removeSwimlane($project_id, $swimlane_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeSwimlane', $project_id);
|
||||
return $this->swimlaneModel->remove($project_id, $swimlane_id);
|
||||
}
|
||||
|
||||
public function disableSwimlane($project_id, $swimlane_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableSwimlane', $project_id);
|
||||
return $this->swimlaneModel->disable($project_id, $swimlane_id);
|
||||
}
|
||||
|
||||
public function enableSwimlane($project_id, $swimlane_id)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableSwimlane', $project_id);
|
||||
return $this->swimlaneModel->enable($project_id, $swimlane_id);
|
||||
}
|
||||
|
||||
public function changeSwimlanePosition($project_id, $swimlane_id, $position)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeSwimlanePosition', $project_id);
|
||||
return $this->swimlaneModel->changePosition($project_id, $swimlane_id, $position);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Api\Authorization\TaskAuthorization;
|
||||
use Kanboard\Core\ExternalLink\ExternalLinkManager;
|
||||
use Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound;
|
||||
|
||||
/**
|
||||
* Task External Link API controller
|
||||
*
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskExternalLinkProcedure extends BaseProcedure
|
||||
{
|
||||
public function getExternalTaskLinkTypes()
|
||||
{
|
||||
return $this->externalLinkManager->getTypes();
|
||||
}
|
||||
|
||||
public function getExternalTaskLinkProviderDependencies($providerName)
|
||||
{
|
||||
try {
|
||||
return $this->externalLinkManager->getProvider($providerName)->getDependencies();
|
||||
} catch (ExternalLinkProviderNotFound $e) {
|
||||
$this->logger->error(__METHOD__.': '.$e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getExternalTaskLinkById($task_id, $link_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getExternalTaskLink', $task_id);
|
||||
return $this->taskExternalLinkModel->getById($link_id);
|
||||
}
|
||||
|
||||
public function getAllExternalTaskLinks($task_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getExternalTaskLinks', $task_id);
|
||||
return $this->taskExternalLinkModel->getAll($task_id);
|
||||
}
|
||||
|
||||
public function createExternalTaskLink($task_id, $url, $dependency, $type = ExternalLinkManager::TYPE_AUTO, $title = '')
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createExternalTaskLink', $task_id);
|
||||
|
||||
try {
|
||||
$provider = $this->externalLinkManager
|
||||
->setUserInputText($url)
|
||||
->setUserInputType($type)
|
||||
->find();
|
||||
|
||||
$link = $provider->getLink();
|
||||
|
||||
$values = array(
|
||||
'task_id' => $task_id,
|
||||
'title' => $title ?: $link->getTitle(),
|
||||
'url' => $link->getUrl(),
|
||||
'link_type' => $provider->getType(),
|
||||
'dependency' => $dependency,
|
||||
);
|
||||
|
||||
list($valid, $errors) = $this->externalLinkValidator->validateCreation($values);
|
||||
|
||||
if (! $valid) {
|
||||
$this->logger->error(__METHOD__.': '.var_export($errors));
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->taskExternalLinkModel->create($values);
|
||||
} catch (ExternalLinkProviderNotFound $e) {
|
||||
$this->logger->error(__METHOD__.': '.$e->getMessage());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function updateExternalTaskLink($task_id, $link_id, $title = null, $url = null, $dependency = null)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateExternalTaskLink', $task_id);
|
||||
|
||||
$link = $this->taskExternalLinkModel->getById($link_id);
|
||||
$values = $this->filterValues(array(
|
||||
'title' => $title,
|
||||
'url' => $url,
|
||||
'dependency' => $dependency,
|
||||
));
|
||||
|
||||
$values = array_merge($link, $values);
|
||||
list($valid, $errors) = $this->externalLinkValidator->validateModification($values);
|
||||
|
||||
if (! $valid) {
|
||||
$this->logger->error(__METHOD__.': '.var_export($errors));
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->taskExternalLinkModel->update($values);
|
||||
}
|
||||
|
||||
public function removeExternalTaskLink($task_id, $link_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeExternalTaskLink', $task_id);
|
||||
return $this->taskExternalLinkModel->remove($link_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Api\Authorization\ProjectAuthorization;
|
||||
use Kanboard\Api\Authorization\TaskAuthorization;
|
||||
use Kanboard\Api\Authorization\TaskFileAuthorization;
|
||||
use Kanboard\Core\ObjectStorage\ObjectStorageException;
|
||||
|
||||
/**
|
||||
* File API controller
|
||||
* Task File API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class FileApi extends BaseApi
|
||||
class TaskFileProcedure extends BaseProcedure
|
||||
{
|
||||
public function getTaskFile($file_id)
|
||||
{
|
||||
TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskFile', $file_id);
|
||||
return $this->taskFileModel->getById($file_id);
|
||||
}
|
||||
|
||||
public function getAllTaskFiles($task_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTaskFiles', $task_id);
|
||||
return $this->taskFileModel->getAll($task_id);
|
||||
}
|
||||
|
||||
public function downloadTaskFile($file_id)
|
||||
{
|
||||
TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'downloadTaskFile', $file_id);
|
||||
|
||||
try {
|
||||
$file = $this->taskFileModel->getById($file_id);
|
||||
|
||||
|
|
@ -33,59 +40,31 @@ class FileApi extends BaseApi
|
|||
} catch (ObjectStorageException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function createTaskFile($project_id, $task_id, $filename, $blob)
|
||||
{
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTaskFile', $project_id);
|
||||
|
||||
try {
|
||||
return $this->taskFileModel->uploadContent($task_id, $filename, $blob);
|
||||
} catch (ObjectStorageException $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
$this->logger->error(__METHOD__.': '.$e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function removeTaskFile($file_id)
|
||||
{
|
||||
TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTaskFile', $file_id);
|
||||
return $this->taskFileModel->remove($file_id);
|
||||
}
|
||||
|
||||
public function removeAllTaskFiles($task_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeAllTaskFiles', $task_id);
|
||||
return $this->taskFileModel->removeAll($task_id);
|
||||
}
|
||||
|
||||
// Deprecated procedures
|
||||
|
||||
public function getFile($file_id)
|
||||
{
|
||||
return $this->getTaskFile($file_id);
|
||||
}
|
||||
|
||||
public function getAllFiles($task_id)
|
||||
{
|
||||
return $this->getAllTaskFiles($task_id);
|
||||
}
|
||||
|
||||
public function downloadFile($file_id)
|
||||
{
|
||||
return $this->downloadTaskFile($file_id);
|
||||
}
|
||||
|
||||
public function createFile($project_id, $task_id, $filename, $blob)
|
||||
{
|
||||
return $this->createTaskFile($project_id, $task_id, $filename, $blob);
|
||||
}
|
||||
|
||||
public function removeFile($file_id)
|
||||
{
|
||||
return $this->removeTaskFile($file_id);
|
||||
}
|
||||
|
||||
public function removeAllFiles($task_id)
|
||||
{
|
||||
return $this->removeAllTaskFiles($task_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
use Kanboard\Api\Authorization\TaskAuthorization;
|
||||
use Kanboard\Api\Authorization\TaskLinkAuthorization;
|
||||
|
||||
/**
|
||||
* TaskLink API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskLinkApi extends Base
|
||||
class TaskLinkProcedure extends BaseProcedure
|
||||
{
|
||||
/**
|
||||
* Get a task link
|
||||
|
|
@ -21,6 +22,7 @@ class TaskLinkApi extends Base
|
|||
*/
|
||||
public function getTaskLinkById($task_link_id)
|
||||
{
|
||||
TaskLinkAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskLinkById', $task_link_id);
|
||||
return $this->taskLinkModel->getById($task_link_id);
|
||||
}
|
||||
|
||||
|
|
@ -33,6 +35,7 @@ class TaskLinkApi extends Base
|
|||
*/
|
||||
public function getAllTaskLinks($task_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTaskLinks', $task_id);
|
||||
return $this->taskLinkModel->getAll($task_id);
|
||||
}
|
||||
|
||||
|
|
@ -47,6 +50,7 @@ class TaskLinkApi extends Base
|
|||
*/
|
||||
public function createTaskLink($task_id, $opposite_task_id, $link_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTaskLink', $task_id);
|
||||
return $this->taskLinkModel->create($task_id, $opposite_task_id, $link_id);
|
||||
}
|
||||
|
||||
|
|
@ -62,6 +66,7 @@ class TaskLinkApi extends Base
|
|||
*/
|
||||
public function updateTaskLink($task_link_id, $task_id, $opposite_task_id, $link_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTaskLink', $task_id);
|
||||
return $this->taskLinkModel->update($task_link_id, $task_id, $opposite_task_id, $link_id);
|
||||
}
|
||||
|
||||
|
|
@ -74,6 +79,7 @@ class TaskLinkApi extends Base
|
|||
*/
|
||||
public function removeTaskLink($task_link_id)
|
||||
{
|
||||
TaskLinkAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTaskLink', $task_link_id);
|
||||
return $this->taskLinkModel->remove($task_link_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,39 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Api\Authorization\ProjectAuthorization;
|
||||
use Kanboard\Api\Authorization\TaskAuthorization;
|
||||
use Kanboard\Filter\TaskProjectFilter;
|
||||
use Kanboard\Model\TaskModel;
|
||||
|
||||
/**
|
||||
* Task API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class TaskApi extends BaseApi
|
||||
class TaskProcedure extends BaseProcedure
|
||||
{
|
||||
public function searchTasks($project_id, $query)
|
||||
{
|
||||
$this->checkProjectPermission($project_id);
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'searchTasks', $project_id);
|
||||
return $this->taskLexer->build($query)->withFilter(new TaskProjectFilter($project_id))->toArray();
|
||||
}
|
||||
|
||||
public function getTask($task_id)
|
||||
{
|
||||
$this->checkTaskPermission($task_id);
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTask', $task_id);
|
||||
return $this->formatTask($this->taskFinderModel->getById($task_id));
|
||||
}
|
||||
|
||||
public function getTaskByReference($project_id, $reference)
|
||||
{
|
||||
$this->checkProjectPermission($project_id);
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskByReference', $project_id);
|
||||
return $this->formatTask($this->taskFinderModel->getByReference($project_id, $reference));
|
||||
}
|
||||
|
||||
public function getAllTasks($project_id, $status_id = TaskModel::STATUS_OPEN)
|
||||
{
|
||||
$this->checkProjectPermission($project_id);
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTasks', $project_id);
|
||||
return $this->formatTasks($this->taskFinderModel->getAll($project_id, $status_id));
|
||||
}
|
||||
|
||||
|
|
@ -44,41 +46,44 @@ class TaskApi extends BaseApi
|
|||
|
||||
public function getOverdueTasksByProject($project_id)
|
||||
{
|
||||
$this->checkProjectPermission($project_id);
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getOverdueTasksByProject', $project_id);
|
||||
return $this->taskFinderModel->getOverdueTasksByProject($project_id);
|
||||
}
|
||||
|
||||
public function openTask($task_id)
|
||||
{
|
||||
$this->checkTaskPermission($task_id);
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'openTask', $task_id);
|
||||
return $this->taskStatusModel->open($task_id);
|
||||
}
|
||||
|
||||
public function closeTask($task_id)
|
||||
{
|
||||
$this->checkTaskPermission($task_id);
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'closeTask', $task_id);
|
||||
return $this->taskStatusModel->close($task_id);
|
||||
}
|
||||
|
||||
public function removeTask($task_id)
|
||||
{
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTask', $task_id);
|
||||
return $this->taskModel->remove($task_id);
|
||||
}
|
||||
|
||||
public function moveTaskPosition($project_id, $task_id, $column_id, $position, $swimlane_id = 0)
|
||||
{
|
||||
$this->checkProjectPermission($project_id);
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'moveTaskPosition', $project_id);
|
||||
return $this->taskPositionModel->movePosition($project_id, $task_id, $column_id, $position, $swimlane_id);
|
||||
}
|
||||
|
||||
public function moveTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null)
|
||||
{
|
||||
return $this->taskDuplicationModel->moveToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id);
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'moveTaskToProject', $project_id);
|
||||
return $this->taskProjectMoveModel->moveToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id);
|
||||
}
|
||||
|
||||
public function duplicateTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null)
|
||||
{
|
||||
return $this->taskDuplicationModel->duplicateToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id);
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'duplicateTaskToProject', $project_id);
|
||||
return $this->taskProjectDuplicationModel->duplicateToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id);
|
||||
}
|
||||
|
||||
public function createTask($title, $project_id, $color_id = '', $column_id = 0, $owner_id = 0, $creator_id = 0,
|
||||
|
|
@ -86,8 +91,8 @@ class TaskApi extends BaseApi
|
|||
$recurrence_status = 0, $recurrence_trigger = 0, $recurrence_factor = 0, $recurrence_timeframe = 0,
|
||||
$recurrence_basedate = 0, $reference = '')
|
||||
{
|
||||
$this->checkProjectPermission($project_id);
|
||||
|
||||
ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTask', $project_id);
|
||||
|
||||
if ($owner_id !== 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -127,8 +132,7 @@ class TaskApi extends BaseApi
|
|||
$recurrence_status = null, $recurrence_trigger = null, $recurrence_factor = null,
|
||||
$recurrence_timeframe = null, $recurrence_basedate = null, $reference = null)
|
||||
{
|
||||
$this->checkTaskPermission($id);
|
||||
|
||||
TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTask', $id);
|
||||
$project_id = $this->taskFinderModel->getProjectId($id);
|
||||
|
||||
if ($project_id === 0) {
|
||||
|
|
@ -139,7 +143,7 @@ class TaskApi extends BaseApi
|
|||
return false;
|
||||
}
|
||||
|
||||
$values = array(
|
||||
$values = $this->filterValues(array(
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
'color_id' => $color_id,
|
||||
|
|
@ -155,13 +159,7 @@ class TaskApi extends BaseApi
|
|||
'recurrence_basedate' => $recurrence_basedate,
|
||||
'reference' => $reference,
|
||||
'priority' => $priority,
|
||||
);
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
if (is_null($value)) {
|
||||
unset($values[$key]);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
list($valid) = $this->taskValidator->validateApiModification($values);
|
||||
return $valid && $this->taskModificationModel->update($values);
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
namespace Kanboard\Api\Procedure;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
use LogicException;
|
||||
use Kanboard\Core\Security\Role;
|
||||
use Kanboard\Core\Ldap\Client as LdapClient;
|
||||
|
|
@ -12,10 +11,10 @@ use Kanboard\Core\Ldap\User as LdapUser;
|
|||
/**
|
||||
* User API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @package Kanboard\Api\Procedure
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class UserApi extends Base
|
||||
class UserProcedure extends BaseProcedure
|
||||
{
|
||||
public function getUser($user_id)
|
||||
{
|
||||
|
|
@ -118,19 +117,13 @@ class UserApi extends Base
|
|||
|
||||
public function updateUser($id, $username = null, $name = null, $email = null, $role = null)
|
||||
{
|
||||
$values = array(
|
||||
$values = $this->filterValues(array(
|
||||
'id' => $id,
|
||||
'username' => $username,
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'role' => $role,
|
||||
);
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
if (is_null($value)) {
|
||||
unset($values[$key]);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
list($valid, ) = $this->userValidator->validateApiModification($values);
|
||||
return $valid && $this->userModel->update($values);
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
|
||||
/**
|
||||
* Project API controller
|
||||
*
|
||||
* @package Kanboard\Api
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class ProjectApi extends BaseApi
|
||||
{
|
||||
public function getProjectById($project_id)
|
||||
{
|
||||
$this->checkProjectPermission($project_id);
|
||||
return $this->formatProject($this->projectModel->getById($project_id));
|
||||
}
|
||||
|
||||
public function getProjectByName($name)
|
||||
{
|
||||
return $this->formatProject($this->projectModel->getByName($name));
|
||||
}
|
||||
|
||||
public function getAllProjects()
|
||||
{
|
||||
return $this->formatProjects($this->projectModel->getAll());
|
||||
}
|
||||
|
||||
public function removeProject($project_id)
|
||||
{
|
||||
return $this->projectModel->remove($project_id);
|
||||
}
|
||||
|
||||
public function enableProject($project_id)
|
||||
{
|
||||
return $this->projectModel->enable($project_id);
|
||||
}
|
||||
|
||||
public function disableProject($project_id)
|
||||
{
|
||||
return $this->projectModel->disable($project_id);
|
||||
}
|
||||
|
||||
public function enableProjectPublicAccess($project_id)
|
||||
{
|
||||
return $this->projectModel->enablePublicAccess($project_id);
|
||||
}
|
||||
|
||||
public function disableProjectPublicAccess($project_id)
|
||||
{
|
||||
return $this->projectModel->disablePublicAccess($project_id);
|
||||
}
|
||||
|
||||
public function getProjectActivities(array $project_ids)
|
||||
{
|
||||
return $this->helper->projectActivity->getProjectsEvents($project_ids);
|
||||
}
|
||||
|
||||
public function getProjectActivity($project_id)
|
||||
{
|
||||
$this->checkProjectPermission($project_id);
|
||||
return $this->helper->projectActivity->getProjectEvents($project_id);
|
||||
}
|
||||
|
||||
public function createProject($name, $description = null)
|
||||
{
|
||||
$values = array(
|
||||
'name' => $name,
|
||||
'description' => $description
|
||||
);
|
||||
|
||||
list($valid, ) = $this->projectValidator->validateCreation($values);
|
||||
return $valid ? $this->projectModel->create($values) : false;
|
||||
}
|
||||
|
||||
public function updateProject($id, $name, $description = null)
|
||||
{
|
||||
$values = array(
|
||||
'id' => $id,
|
||||
'name' => $name,
|
||||
'description' => $description
|
||||
);
|
||||
|
||||
list($valid, ) = $this->projectValidator->validateModification($values);
|
||||
return $valid && $this->projectModel->update($values);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Api;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
|
||||
/**
|
||||
* Subtask Time Tracking API controller
|
||||
*
|
||||
* @package api
|
||||
* @author Nikolaos Georgakis
|
||||
*/
|
||||
class SubtaskTimeTrackingApi extends Base
|
||||
{
|
||||
public function hasTimer($subtask_id,$user_id)
|
||||
{
|
||||
return $this->subtaskTimeTrackingModel->hasTimer($subtask_id,$user_id);
|
||||
}
|
||||
|
||||
public function logStartTime($subtask_id,$user_id)
|
||||
{
|
||||
return $this->subtaskTimeTrackingModel->logStartTime($subtask_id,$user_id);
|
||||
}
|
||||
|
||||
public function logEndTime($subtask_id,$user_id)
|
||||
{
|
||||
return $this->subtaskTimeTrackingModel->logEndTime($subtask_id,$user_id);
|
||||
}
|
||||
|
||||
public function getTimeSpent($subtask_id,$user_id)
|
||||
{
|
||||
return $this->subtaskTimeTrackingModel->getTimeSpent($subtask_id,$user_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +45,8 @@ class ReverseProxyAuth extends Base implements PreAuthenticationProviderInterfac
|
|||
$username = $this->request->getRemoteUser();
|
||||
|
||||
if (! empty($username)) {
|
||||
$this->userInfo = new ReverseProxyUserProvider($username);
|
||||
$userProfile = $this->userModel->getByUsername($username);
|
||||
$this->userInfo = new ReverseProxyUserProvider($username, $userProfile ?: array());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ class TotpAuth extends Base implements PostAuthenticationProviderInterface
|
|||
return '';
|
||||
}
|
||||
|
||||
return GoogleAuthenticator::getQrCodeUrl('totp', $label, $this->secret);
|
||||
$options = array('issuer' => TOTP_ISSUER);
|
||||
return GoogleAuthenticator::getQrCodeUrl('totp', $label, $this->secret, null, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -139,6 +140,7 @@ class TotpAuth extends Base implements PostAuthenticationProviderInterface
|
|||
return '';
|
||||
}
|
||||
|
||||
return GoogleAuthenticator::getKeyUri('totp', $label, $this->secret);
|
||||
$options = array('issuer' => TOTP_ISSUER);
|
||||
return GoogleAuthenticator::getKeyUri('totp', $label, $this->secret, null, $options);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ class TaskOverdueNotificationCommand extends BaseCommand
|
|||
$this->userNotificationModel->sendUserNotification(
|
||||
$user,
|
||||
TaskModel::EVENT_OVERDUE,
|
||||
array('tasks' => $user_tasks, 'project_name' => implode(", ", $project_names))
|
||||
array('tasks' => $user_tasks, 'project_name' => implode(', ', $project_names))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class ActionCreationController extends BaseController
|
|||
'colors_list' => $this->colorModel->getList(),
|
||||
'categories_list' => $this->categoryModel->getList($project['id']),
|
||||
'links_list' => $this->linkModel->getList(0, false),
|
||||
'priorities_list' => $this->projectModel->getPriorities($project),
|
||||
'priorities_list' => $this->projectTaskPriorityModel->getPriorities($project),
|
||||
'project' => $project,
|
||||
'available_actions' => $this->actionManager->getAvailableActions(),
|
||||
'events' => $this->actionManager->getCompatibleEvents($values['action_name']),
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class AnalyticController extends BaseController
|
|||
'metrics' => $this->projectDailyStatsModel->getRawMetrics($project['id'], $from, $to),
|
||||
'date_format' => $this->configModel->get('application_date_format'),
|
||||
'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
|
||||
'title' => t('Lead and Cycle time for "%s"', $project['name']),
|
||||
'title' => t('Lead and cycle time'),
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ class AnalyticController extends BaseController
|
|||
'project' => $project,
|
||||
'paginator' => $paginator,
|
||||
'metrics' => $this->estimatedTimeComparisonAnalytic->build($project['id']),
|
||||
'title' => t('Compare hours for "%s"', $project['name']),
|
||||
'title' => t('Estimated vs actual time'),
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ class AnalyticController extends BaseController
|
|||
$this->response->html($this->helper->layout->analytic('analytic/avg_time_columns', array(
|
||||
'project' => $project,
|
||||
'metrics' => $this->averageTimeSpentColumnAnalytic->build($project['id']),
|
||||
'title' => t('Average time spent into each column for "%s"', $project['name']),
|
||||
'title' => t('Average time into each column'),
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ class AnalyticController extends BaseController
|
|||
$this->response->html($this->helper->layout->analytic('analytic/tasks', array(
|
||||
'project' => $project,
|
||||
'metrics' => $this->taskDistributionAnalytic->build($project['id']),
|
||||
'title' => t('Task repartition for "%s"', $project['name']),
|
||||
'title' => t('Task distribution'),
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ class AnalyticController extends BaseController
|
|||
$this->response->html($this->helper->layout->analytic('analytic/users', array(
|
||||
'project' => $project,
|
||||
'metrics' => $this->userDistributionAnalytic->build($project['id']),
|
||||
'title' => t('User repartition for "%s"', $project['name']),
|
||||
'title' => t('User repartition'),
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ class AnalyticController extends BaseController
|
|||
*/
|
||||
public function cfd()
|
||||
{
|
||||
$this->commonAggregateMetrics('analytic/cfd', 'total', 'Cumulative flow diagram for "%s"');
|
||||
$this->commonAggregateMetrics('analytic/cfd', 'total', t('Cumulative flow diagram'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -129,7 +129,7 @@ class AnalyticController extends BaseController
|
|||
*/
|
||||
public function burndown()
|
||||
{
|
||||
$this->commonAggregateMetrics('analytic/burndown', 'score', 'Burndown chart for "%s"');
|
||||
$this->commonAggregateMetrics('analytic/burndown', 'score', t('Burndown chart'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -157,7 +157,7 @@ class AnalyticController extends BaseController
|
|||
'project' => $project,
|
||||
'date_format' => $this->configModel->get('application_date_format'),
|
||||
'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
|
||||
'title' => t($title, $project['name']),
|
||||
'title' => $title,
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ class BoardAjaxController extends BaseController
|
|||
'board_highlight_period' => $this->configModel->get('board_highlight_period'),
|
||||
'swimlanes' => $this->taskLexer
|
||||
->build($this->userSession->getFilters($project_id))
|
||||
->format(BoardFormatter::getInstance($this->container)->setProjectId($project_id))
|
||||
->format(BoardFormatter::getInstance($this->container)->withProjectId($project_id))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,9 +107,9 @@ class BoardTooltipController extends BaseController
|
|||
|
||||
$this->response->html($this->template->render('task_recurrence/info', array(
|
||||
'task' => $task,
|
||||
'recurrence_trigger_list' => $this->taskModel->getRecurrenceTriggerList(),
|
||||
'recurrence_timeframe_list' => $this->taskModel->getRecurrenceTimeframeList(),
|
||||
'recurrence_basedate_list' => $this->taskModel->getRecurrenceBasedateList(),
|
||||
'recurrence_trigger_list' => $this->taskRecurrenceModel->getRecurrenceTriggerList(),
|
||||
'recurrence_timeframe_list' => $this->taskRecurrenceModel->getRecurrenceTimeframeList(),
|
||||
'recurrence_basedate_list' => $this->taskRecurrenceModel->getRecurrenceBasedateList(),
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,11 @@ class BoardViewController extends BaseController
|
|||
|
||||
$this->response->html($this->helper->layout->app('board/view_public', array(
|
||||
'project' => $project,
|
||||
'swimlanes' => $this->boardModel->getBoard($project['id']),
|
||||
'swimlanes' => BoardFormatter::getInstance($this->container)
|
||||
->withProjectId($project['id'])
|
||||
->withQuery($this->taskFinderModel->getExtendedQuery())
|
||||
->format()
|
||||
,
|
||||
'title' => $project['name'],
|
||||
'description' => $project['description'],
|
||||
'no_layout' => true,
|
||||
|
|
@ -59,7 +63,7 @@ class BoardViewController extends BaseController
|
|||
'board_highlight_period' => $this->configModel->get('board_highlight_period'),
|
||||
'swimlanes' => $this->taskLexer
|
||||
->build($search)
|
||||
->format(BoardFormatter::getInstance($this->container)->setProjectId($project['id']))
|
||||
->format(BoardFormatter::getInstance($this->container)->withProjectId($project['id']))
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,15 @@ class ColumnController extends BaseController
|
|||
list($valid, $errors) = $this->columnValidator->validateCreation($values);
|
||||
|
||||
if ($valid) {
|
||||
if ($this->columnModel->create($project['id'], $values['title'], $values['task_limit'], $values['description']) !== false) {
|
||||
$result = $this->columnModel->create(
|
||||
$project['id'],
|
||||
$values['title'],
|
||||
$values['task_limit'],
|
||||
$values['description'],
|
||||
isset($values['hide_in_dashboard']) ? $values['hide_in_dashboard'] : 0
|
||||
);
|
||||
|
||||
if ($result !== false) {
|
||||
$this->flash->success(t('Column created successfully.'));
|
||||
return $this->response->redirect($this->helper->url->to('ColumnController', 'index', array('project_id' => $project['id'])), true);
|
||||
} else {
|
||||
|
|
@ -111,7 +119,15 @@ class ColumnController extends BaseController
|
|||
list($valid, $errors) = $this->columnValidator->validateModification($values);
|
||||
|
||||
if ($valid) {
|
||||
if ($this->columnModel->update($values['id'], $values['title'], $values['task_limit'], $values['description'])) {
|
||||
$result = $this->columnModel->update(
|
||||
$values['id'],
|
||||
$values['title'],
|
||||
$values['task_limit'],
|
||||
$values['description'],
|
||||
isset($values['hide_in_dashboard']) ? $values['hide_in_dashboard'] : 0
|
||||
);
|
||||
|
||||
if ($result) {
|
||||
$this->flash->success(t('Board updated successfully.'));
|
||||
return $this->response->redirect($this->helper->url->to('ColumnController', 'index', array('project_id' => $project['id'])));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@
|
|||
|
||||
namespace Kanboard\Controller;
|
||||
|
||||
use Kanboard\Model\ProjectModel;
|
||||
use Kanboard\Model\SubtaskModel;
|
||||
|
||||
/**
|
||||
* Dashboard Controller
|
||||
*
|
||||
|
|
@ -13,63 +10,6 @@ use Kanboard\Model\SubtaskModel;
|
|||
*/
|
||||
class DashboardController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Get project pagination
|
||||
*
|
||||
* @access private
|
||||
* @param integer $user_id
|
||||
* @param string $action
|
||||
* @param integer $max
|
||||
* @return \Kanboard\Core\Paginator
|
||||
*/
|
||||
private function getProjectPaginator($user_id, $action, $max)
|
||||
{
|
||||
return $this->paginator
|
||||
->setUrl('DashboardController', $action, array('pagination' => 'projects', 'user_id' => $user_id))
|
||||
->setMax($max)
|
||||
->setOrder(ProjectModel::TABLE.'.name')
|
||||
->setQuery($this->projectModel->getQueryColumnStats($this->projectPermissionModel->getActiveProjectIds($user_id)))
|
||||
->calculateOnlyIf($this->request->getStringParam('pagination') === 'projects');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get task pagination
|
||||
*
|
||||
* @access private
|
||||
* @param integer $user_id
|
||||
* @param string $action
|
||||
* @param integer $max
|
||||
* @return \Kanboard\Core\Paginator
|
||||
*/
|
||||
private function getTaskPaginator($user_id, $action, $max)
|
||||
{
|
||||
return $this->paginator
|
||||
->setUrl('DashboardController', $action, array('pagination' => 'tasks', 'user_id' => $user_id))
|
||||
->setMax($max)
|
||||
->setOrder('tasks.id')
|
||||
->setQuery($this->taskFinderModel->getUserQuery($user_id))
|
||||
->calculateOnlyIf($this->request->getStringParam('pagination') === 'tasks');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subtask pagination
|
||||
*
|
||||
* @access private
|
||||
* @param integer $user_id
|
||||
* @param string $action
|
||||
* @param integer $max
|
||||
* @return \Kanboard\Core\Paginator
|
||||
*/
|
||||
private function getSubtaskPaginator($user_id, $action, $max)
|
||||
{
|
||||
return $this->paginator
|
||||
->setUrl('DashboardController', $action, array('pagination' => 'subtasks', 'user_id' => $user_id))
|
||||
->setMax($max)
|
||||
->setOrder('tasks.id')
|
||||
->setQuery($this->subtaskModel->getUserQuery($user_id, array(SubTaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS)))
|
||||
->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard overview
|
||||
*
|
||||
|
|
@ -80,10 +20,10 @@ class DashboardController extends BaseController
|
|||
$user = $this->getUser();
|
||||
|
||||
$this->response->html($this->helper->layout->dashboard('dashboard/show', array(
|
||||
'title' => t('Dashboard'),
|
||||
'project_paginator' => $this->getProjectPaginator($user['id'], 'show', 10),
|
||||
'task_paginator' => $this->getTaskPaginator($user['id'], 'show', 10),
|
||||
'subtask_paginator' => $this->getSubtaskPaginator($user['id'], 'show', 10),
|
||||
'title' => t('Dashboard for %s', $this->helper->user->getFullname($user)),
|
||||
'project_paginator' => $this->projectPagination->getDashboardPaginator($user['id'], 'show', 10),
|
||||
'task_paginator' => $this->taskPagination->getDashboardPaginator($user['id'], 'show', 10),
|
||||
'subtask_paginator' => $this->subtaskPagination->getDashboardPaginator($user['id'], 'show', 10),
|
||||
'user' => $user,
|
||||
)));
|
||||
}
|
||||
|
|
@ -98,8 +38,8 @@ class DashboardController extends BaseController
|
|||
$user = $this->getUser();
|
||||
|
||||
$this->response->html($this->helper->layout->dashboard('dashboard/tasks', array(
|
||||
'title' => t('My tasks'),
|
||||
'paginator' => $this->getTaskPaginator($user['id'], 'tasks', 50),
|
||||
'title' => t('Tasks overview for %s', $this->helper->user->getFullname($user)),
|
||||
'paginator' => $this->taskPagination->getDashboardPaginator($user['id'], 'tasks', 50),
|
||||
'user' => $user,
|
||||
)));
|
||||
}
|
||||
|
|
@ -114,8 +54,8 @@ class DashboardController extends BaseController
|
|||
$user = $this->getUser();
|
||||
|
||||
$this->response->html($this->helper->layout->dashboard('dashboard/subtasks', array(
|
||||
'title' => t('My subtasks'),
|
||||
'paginator' => $this->getSubtaskPaginator($user['id'], 'subtasks', 50),
|
||||
'title' => t('Subtasks overview for %s', $this->helper->user->getFullname($user)),
|
||||
'paginator' => $this->subtaskPagination->getDashboardPaginator($user['id'], 'subtasks', 50),
|
||||
'user' => $user,
|
||||
)));
|
||||
}
|
||||
|
|
@ -130,8 +70,8 @@ class DashboardController extends BaseController
|
|||
$user = $this->getUser();
|
||||
|
||||
$this->response->html($this->helper->layout->dashboard('dashboard/projects', array(
|
||||
'title' => t('My projects'),
|
||||
'paginator' => $this->getProjectPaginator($user['id'], 'projects', 25),
|
||||
'title' => t('Projects overview for %s', $this->helper->user->getFullname($user)),
|
||||
'paginator' => $this->projectPagination->getDashboardPaginator($user['id'], 'projects', 25),
|
||||
'user' => $user,
|
||||
)));
|
||||
}
|
||||
|
|
@ -146,7 +86,7 @@ class DashboardController extends BaseController
|
|||
$user = $this->getUser();
|
||||
|
||||
$this->response->html($this->helper->layout->dashboard('dashboard/activity', array(
|
||||
'title' => t('My activity stream'),
|
||||
'title' => t('Activity stream for %s', $this->helper->user->getFullname($user)),
|
||||
'events' => $this->helper->projectActivity->getProjectsEvents($this->projectPermissionModel->getActiveProjectIds($user['id']), 100),
|
||||
'user' => $user,
|
||||
)));
|
||||
|
|
@ -159,9 +99,11 @@ class DashboardController extends BaseController
|
|||
*/
|
||||
public function calendar()
|
||||
{
|
||||
$user = $this->getUser();
|
||||
|
||||
$this->response->html($this->helper->layout->dashboard('dashboard/calendar', array(
|
||||
'title' => t('My calendar'),
|
||||
'user' => $this->getUser(),
|
||||
'title' => t('Calendar for %s', $this->helper->user->getFullname($user)),
|
||||
'user' => $user,
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +117,7 @@ class DashboardController extends BaseController
|
|||
$user = $this->getUser();
|
||||
|
||||
$this->response->html($this->helper->layout->dashboard('dashboard/notifications', array(
|
||||
'title' => t('My notifications'),
|
||||
'title' => t('Notifications for %s', $this->helper->user->getFullname($user)),
|
||||
'notifications' => $this->userUnreadNotificationModel->getAll($user['id']),
|
||||
'user' => $user,
|
||||
)));
|
||||
|
|
|
|||
|
|
@ -20,16 +20,7 @@ class DocumentationController extends BaseController
|
|||
$page = 'index';
|
||||
}
|
||||
|
||||
if ($this->languageModel->getCurrentLanguage() === 'fr_FR') {
|
||||
$filename = __DIR__.'/../../doc/fr/' . $page . '.markdown';
|
||||
} else {
|
||||
$filename = __DIR__ . '/../../doc/' . $page . '.markdown';
|
||||
}
|
||||
|
||||
if (!file_exists($filename)) {
|
||||
$filename = __DIR__.'/../../doc/index.markdown';
|
||||
}
|
||||
|
||||
$filename = $this->getPageFilename($page);
|
||||
$this->response->html($this->helper->layout->app('doc/show', $this->render($filename)));
|
||||
}
|
||||
|
||||
|
|
@ -83,10 +74,63 @@ class DocumentationController extends BaseController
|
|||
*/
|
||||
public function replaceImageUrl(array $matches)
|
||||
{
|
||||
if ($this->languageModel->getCurrentLanguage() === 'fr_FR') {
|
||||
return '('.$this->helper->url->base().'doc/fr/'.$matches[1].')';
|
||||
return '('.$this->getFileBaseUrl($matches[1]).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Markdown file according to the current language
|
||||
*
|
||||
* @access private
|
||||
* @param string $page
|
||||
* @return string
|
||||
*/
|
||||
private function getPageFilename($page)
|
||||
{
|
||||
return $this->getFileLocation($page . '.markdown') ?:
|
||||
implode(DIRECTORY_SEPARATOR, array(ROOT_DIR, 'doc', 'index.markdown'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get base URL for Markdown links
|
||||
*
|
||||
* @access private
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
private function getFileBaseUrl($filename)
|
||||
{
|
||||
$language = $this->languageModel->getCurrentLanguage();
|
||||
$path = $this->getFileLocation($filename);
|
||||
|
||||
if (strpos($path, $language) !== false) {
|
||||
$url = implode('/', array('doc', $language, $filename));
|
||||
} else {
|
||||
$url = implode('/', array('doc', $filename));
|
||||
}
|
||||
|
||||
return '('.$this->helper->url->base().'doc/'.$matches[1].')';
|
||||
return $this->helper->url->base().$url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file location according to the current language
|
||||
*
|
||||
* @access private
|
||||
* @param string $filename
|
||||
* @return string
|
||||
*/
|
||||
private function getFileLocation($filename)
|
||||
{
|
||||
$files = array(
|
||||
implode(DIRECTORY_SEPARATOR, array(ROOT_DIR, 'doc', $this->languageModel->getCurrentLanguage(), $filename)),
|
||||
implode(DIRECTORY_SEPARATOR, array(ROOT_DIR, 'doc', $filename)),
|
||||
);
|
||||
|
||||
foreach ($files as $filename) {
|
||||
if (file_exists($filename)) {
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,22 +31,23 @@ class ExportController extends BaseController
|
|||
$data = $this->$model->$method($project['id'], $from, $to);
|
||||
$this->response->withFileDownload($filename.'.csv');
|
||||
$this->response->csv($data);
|
||||
}
|
||||
} else {
|
||||
|
||||
$this->response->html($this->helper->layout->project('export/'.$action, array(
|
||||
'values' => array(
|
||||
'controller' => 'ExportController',
|
||||
'action' => $action,
|
||||
'project_id' => $project['id'],
|
||||
'from' => $from,
|
||||
'to' => $to,
|
||||
),
|
||||
'errors' => array(),
|
||||
'date_format' => $this->configModel->get('application_date_format'),
|
||||
'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
|
||||
'project' => $project,
|
||||
'title' => $page_title,
|
||||
), 'export/sidebar'));
|
||||
$this->response->html($this->helper->layout->project('export/'.$action, array(
|
||||
'values' => array(
|
||||
'controller' => 'ExportController',
|
||||
'action' => $action,
|
||||
'project_id' => $project['id'],
|
||||
'from' => $from,
|
||||
'to' => $to,
|
||||
),
|
||||
'errors' => array(),
|
||||
'date_format' => $this->configModel->get('application_date_format'),
|
||||
'date_formats' => $this->dateParser->getAvailableFormats($this->dateParser->getDateFormats()),
|
||||
'project' => $project,
|
||||
'title' => $page_title,
|
||||
), 'export/sidebar'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -76,7 +77,7 @@ class ExportController extends BaseController
|
|||
*/
|
||||
public function summary()
|
||||
{
|
||||
$this->common('projectDailyColumnStats', 'getAggregatedMetrics', t('Summary'), 'summary', t('Daily project summary export'));
|
||||
$this->common('projectDailyColumnStatsModel', 'getAggregatedMetrics', t('Summary'), 'summary', t('Daily project summary export'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue