3 * Copyright (C) 2013 Vitaliy Pylypiv <vitaliy.pylypiv@gmail.com>
4 * Copyright 2016, Stéphane-Eymeric Bredtthauer - TrivialDev
6 * This file is part of FusionForge.
8 * FusionForge is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published
10 * by the Free Software Foundation; either version 2 of the License,
11 * or (at your option) any later version.
13 * FusionForge is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 define('RELEASE_OF_TASK', 1);
24 define('RELEASE_OF_USER_STORY', 2);
26 require_once $gfcommon.'include/FFError.class.php';
27 require_once $gfplugins.'taskboard/common/TaskBoardColumn.class.php';
28 require_once $gfplugins.'taskboard/common/TaskBoardRelease.class.php';
31 * Factory method which creates a taskboard from a taskboard ID
33 * @param int The taskboard ID
34 * @param array The result array, if it's passed in
35 * @return object TaskBoard object
37 function &taskboard_get_object($taskboard_id, $data = false) {
38 static $trackers = array();
40 if( !array_key_exists($taskboard_id, $trackers)) {
41 $res = db_query_params('SELECT * FROM plugin_taskboard WHERE taskboard_id=$1', array($taskboard_id));
42 if (db_numrows($res) <1) {
45 $data = db_fetch_array($res);
47 $Group = group_get_object($data['group_id']);
48 $trackers[$taskboard_id] = new TaskBoard($Group, $data);
50 return $trackers[$taskboard_id];
54 * Initialize a task board
56 function &taskboard_init($group_id) {
58 $res = db_query_params('INSERT INTO plugin_taskboard(group_id) VALUES($1)', array($group_id));
60 $this->setError(db_error());
64 $taskboard_id=db_insertid($res,'plugin_taskboard','taskboard_id');
65 if ($taskboard_id==0) {
69 $Group = group_get_object($group_id);
74 $Taskboard = new TaskBoard($Group, $taskboard_id);
84 class TaskBoard extends FFError {
93 * Trackers adapter object
100 * Array of taskboard data.
102 * @var array $data_array.
106 function TaskBoard($Group, $data = false) {
107 parent::__construct();
108 if (!$Group || !is_object($Group)) {
109 $this->setError(_('No Valid Group Object'));
112 if ($Group->isError()) {
113 $this->setError(_('Taskboard')._(': ').$Group->getErrorMessage());
117 $this->Group = $Group;
120 if (is_array($data)) {
121 $this->data_array =& $data;
122 if ($this->data_array['group_id'] != $this->Group->getID()) {
123 $this->setError('Group_id in db result does not match Group Object');
124 $this->data_array = null;
128 $this->fetchData($data);
132 $plugins_taskboard_trackers_adapter_class = forge_get_config('trackers_adapter_class', 'taskboard');
133 if( !isset($plugins_taskboard_trackers_adapter_class) ) {
134 $plugins_taskboard_trackers_adapter_class = 'TaskBoardBasicAdapter';
137 $plugins_taskboard_trackers_adapter_module = $gfplugins.'taskboard/common/adapters/' . $plugins_taskboard_trackers_adapter_class . '.class.php';
139 require_once( $plugins_taskboard_trackers_adapter_module );
140 $this->TrackersAdapter = new $plugins_taskboard_trackers_adapter_class( $this );
145 * create - create a row in the taskboards table
147 * @param array list of trackers IDs, linked to the taskboard
148 * @param array has of card background colors (key - tracker id, value - bg color)
149 * @param string Alias for of 'select' extra field used for release/sprint
150 * @param string Tracker type of extra field used for release/sprint (1 - task trackers, 2 - user story tracker)
151 * @param string Used for cost calculations together with remaining_cost_field_alias if specified
152 * @param string Used for cost calculations together with estimated_cost_field_alias if specified
154 * @return true on success / false on failure.
156 function create($name, $description = '', $trackers = array(), $bgcolors = array(), $release_field_alias = NULL, $release_field_tracker = 1,
157 $estimated_cost_field_alias = NULL, $remaining_cost_field_alias = '',
158 $user_stories_tracker = NULL, $user_stories_reference_field = NULL,
159 $user_stories_sort_field = NULL, $first_column_by_default = 1) {
161 //$estimated_cost_field = ''; // TODO define alias by default in configuration file
162 //$remaining_cost_field = ''; // TODO define alias by default in configuration file
163 //$user_stories_reference_field = ''; // TODO define alias by default in configuration file
164 //$user_stories_sort_field = ''; // TODO define alias by default in configuration file
169 if (!session_loggedin()) {
170 $this->setError(_('Must Be Logged In'));
176 $res = db_query_params(
177 'INSERT INTO plugin_taskboard(taskboard_name, description, group_id, release_field_alias, release_field_tracker, estimated_cost_field_alias,
178 remaining_cost_field_alias, user_stories_group_artifact_id, user_stories_reference_field_alias,user_stories_sort_field_alias,
179 first_column_by_default) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)',
180 array($name, $description, $this->Group->getID(), $release_field_alias, $release_field_tracker, $estimated_cost_field_alias,
181 $remaining_cost_field_alias, ( $user_stories_tracker ? $user_stories_tracker: NULL ),
182 $user_stories_reference_field, $user_stories_sort_field, $first_column_by_default)
185 $this->setError(_('Cannot create taskboard'));
188 $this->data_array['taskboard_id'] = db_insertid($res,'plugin_taskboard','taskboard_id');
191 if( $ret && is_array($trackers)) {
192 foreach( $trackers as $tracker_id ) {
193 $ret = $this->addUsedTracker( $tracker_id, ( array_key_exists($tracker_id, $bgcolors) ? $bgcolors[$tracker_id] : NULL) );
197 // TODO columns initialization
203 $this->data_array['taskboard_id'] = NULL;
210 * update - update a row in the taskboards table
212 * @param array list of trackers IDs, linked to the taskboard
213 * @param array has of card background colors (key - tracker id, value - bg color)
214 * @param string Alias for of 'select' extra field used for release/sprint
215 * @param string Tracke type of extra field used for release/sprint (1 - task trackers, 2 - user story tracker)
216 * @param string Used for cost calculations together with remaining_cost_field_alias if specified
217 * @param string Used for cost calculations together with estimated_cost_field_alias if specified
219 * @return true on success / false on failure.
221 function update($name, $description, $trackers=array(), $bgcolors=array(), $release_field_alias = NULL, $release_field_tracker = 1,
222 $estimated_cost_field_alias = NULL, $remaining_cost_field_alias = NULL,
223 $user_stories_tracker = NULL, $user_stories_reference_field = NULL, $user_stories_sort_field = NULL, $first_column_by_default = 1 ) {
227 if (!session_loggedin()) {
228 $this->setError(_('Must Be Logged In'));
232 if ($name!=$this->getName() || $description!=$this->getDescription()) {
233 $updateOnlyName = true;
235 $updateOnlyName = false;
238 if( count($trackers) == 0 && !$updateOnlyName) {
239 $this->setError(_('Taskboard must be linked at least to one tracker'));
245 if($updateOnlyName) {
246 $res = db_query_params(
247 'UPDATE plugin_taskboard SET taskboard_name=$1, description=$2 WHERE taskboard_id=$3',
248 array($name, $description, $this->getID()));
250 $res = db_query_params(
251 'UPDATE plugin_taskboard SET taskboard_name=$1, description=$2, release_field_alias=$3, release_field_tracker=$4,
252 estimated_cost_field_alias=$5, remaining_cost_field_alias=$6, user_stories_group_artifact_id=$7,
253 user_stories_reference_field_alias=$8, user_stories_sort_field_alias=$9,
254 first_column_by_default=$10 WHERE taskboard_id=$11',
256 $name, $description, $release_field_alias, $release_field_tracker ,
257 $estimated_cost_field_alias, $remaining_cost_field_alias, ( $user_stories_tracker ? $user_stories_tracker: NULL),
258 $user_stories_reference_field, $user_stories_sort_field,
259 $first_column_by_default, $this->getID())
263 $this->setError(_('Cannot update taskboard'));
270 if($ret && !$updateOnlyName) {
271 $old_trackers = $this->getUsedTrackersIds();
272 foreach($trackers as $tracker_id) {
273 if(in_array($tracker_id, $old_trackers)) {
275 $ret = $this->updateUsedTracker(
277 (array_key_exists($tracker_id, $bgcolors) ? $bgcolors[$tracker_id] : NULL)
281 $ret = $this->addUsedTracker(
283 (array_key_exists($tracker_id, $bgcolors) ? $bgcolors[$tracker_id] : NULL)
288 foreach($old_trackers as $tracker_id){
289 if(!in_array($tracker_id, $trackers)) {
290 $ret = $this->deleteUsedTracker($tracker_id);
299 $this->data_array['taskboard_id'] = NULL;
307 * delete - delete taskboard
312 $res = db_query_params('DELETE FROM plugin_taskboard WHERE taskboard_id = $1', array($this->getID()));
314 $this->setError(_('Taskboard')._(': ')._('Cannot delete taskboard'));
321 * _checkExtraFields() - check where extra field exists in the tracker
324 private function _checkExtraFields($group_artifacts, $alias) {
327 /* TODO How to get ArtifactType objects ?
328 foreach($group_artifacts as $group_artifacts) {
337 * fetchData - re-fetch the data for this TaskBoard from the database.
339 * @param int The taskboard ID.
340 * @return boolean success.
342 function fetchData($taskboard_id = NULL) {
344 $taskboard_id = $this->getID();
346 $res = db_query_params('SELECT * FROM plugin_taskboard WHERE taskboard_id=$1', array($taskboard_id));
347 if (!$res || db_numrows($res) < 1) {
348 $this->setError(_('Taskboard')._(': ')._('Invalid TaskBoardID'));
351 $this->data_array = db_fetch_array($res);
352 db_free_result($res);
357 * getID - get this TaskBoardID.
359 * @return int The taskboard_id
362 return $this->data_array['taskboard_id'];
366 * getName - get this TaskBoard Name.
368 * @return string The taskboard_name
371 return $this->data_array['taskboard_name'];
375 * getDescription - get this TaskBoard Description.
377 * @return string The taskboard description
379 function getDescription() {
380 return $this->data_array['description'];
384 * getReleaseField - get alias of field, used for release/sprint
386 * @return string extra field alias
388 function getReleaseField() {
389 return $this->data_array['release_field_alias'];
393 * getReleaseFieldTracker - get a source tracker type of field, used for release/sprint
395 * @return integer 1 - tasks tracker, 2 - user story tracker
397 function getReleaseFieldTracker() {
398 return $this->data_array['release_field_tracker'];
402 * getEstimatedCostField - get alias of field, used for estimated cost value
404 * @return string extra field alias
406 function getEstimatedCostField() {
407 return $this->data_array['estimated_cost_field_alias'];
411 * getRemainingCostField - get alias of field, used for remaining cost value
413 * @return string extra field alias
415 function getRemainingCostField() {
416 return $this->data_array['remaining_cost_field_alias'];
420 * getUserStoriesTrackerID - get identifier of tracker, used for user stories
422 * @return integer tracker identifier
424 function getUserStoriesTrackerID() {
425 return $this->data_array['user_stories_group_artifact_id'];
429 * getUserStoriesReferenceField - get alias of field, used as a reference to user stiry artifact
431 * @return string extra field alias
433 function getUserStoriesReferenceField() {
434 return $this->data_array['user_stories_reference_field_alias'];
438 * getUserStoriesSortField - get alias of field, used as for user stories sorting (DESC)
440 * @return string extra field alias
442 function getUserStoriesSortField() {
443 return $this->data_array['user_stories_sort_field_alias'];
447 * getFirstColumnByDefault
451 function getFirstColumnByDefault() {
452 return $this->data_array['first_column_by_default'];
457 * getUsedTrackersIds - get identifiers of used trackers
461 function getUsedTrackersIds() {
462 $res = db_query_params('SELECT * FROM plugin_taskboard_trackers WHERE taskboard_id = $1', array ($this->getID()));
464 $this->setError(_('Taskboard')._(': ')._('Cannot get list of used trackers.'));
469 while($row = db_fetch_array($res)) {
470 $trackers[] = $row['group_artifact_id'];
472 db_free_result($res);
477 * getUsedTrackersiData - get data of used trackers
481 function getUsedTrackersData() {
482 $res = db_query_params('SELECT * FROM plugin_taskboard_trackers WHERE taskboard_id = $1', array ($this->getID()));
484 $this->setError(_('Taskboard')._(': ')._('Cannot get list of used trackers.'));
489 while( $row = db_fetch_array($res)) {
492 db_free_result($res);
497 * cleanUsedTrackers - empty list of trackers, used with taskboard
501 function cleanUsedTrackers() {
502 $res = db_query_params('DELETE FROM plugin_taskboard_trackers WHERE taskboard_id = $1', array ($this->getID()));
504 $this->setError(_('Taskboard')._(': ')._('Cannot empty list of used trackers.'));
512 * addUsedTracker - add a tracker to use with taskboard
514 * @param int tracker identifier
515 * @param string optional card background color
519 function addUsedTracker($tracker_id, $bgcolor='') {
520 $res = db_query_params('INSERT INTO plugin_taskboard_trackers(taskboard_id, group_artifact_id, card_background_color) VALUES($1, $2, $3)', array($this->getID(), $tracker_id, $bgcolor));
522 $this->setError(_('Taskboard')._(': ')._('Cannot add used tracker'));
530 * updateUsedTracker - update used tracker
532 * @param int tracker identifier
533 * @param string optional card background color
537 function updateUsedTracker($tracker_id, $bgcolor = '') {
538 $res = db_query_params('UPDATE plugin_taskboard_trackers SET card_background_color = $1 WHERE group_artifact_id = $2', array($bgcolor, $tracker_id));
540 $this->setError(_('Taskboard')._(': ')._('Cannot update used tracker'));
548 * deleteUsedTracker - delete used tracker
550 * @param int tracker identifier
554 function deleteUsedTracker($tracker_id) {
555 $res = db_query_params('DELETE FROM plugin_taskboard_trackers WHERE group_artifact_id = $1', array($tracker_id));
557 $this->setError(_('Taskboard')._(': ')._('Cannot delete used tracker'));
565 * getUserStories - get taskboard user stories
569 function getUserStories($release = NULL, $assigned_to = NULL) {
573 'title' => _('Unlinked tasks'),
574 'description' => _('Tasks, which are not linked to any user story'),
580 $user_stories_sort_field = $this->getUserStoriesSortField();
581 $user_stories_sort_extra_field_id = NULL;
582 if ($user_stories_sort_field) {
583 $ef = $this->TrackersAdapter->getFieldsIds($this->getUserStoriesTrackerID());
584 if ( array_key_exists($user_stories_sort_field ,$ef) ) {
585 $user_stories_sort_extra_field_id = $ef[ $user_stories_sort_field ];
587 $this->setError(_('Configured extra field for userstories sorting is not found.'));
592 $task_release = NULL;
593 $user_story_release = NULL;
595 if ($this->getReleaseFieldTracker() == RELEASE_OF_TASK) {
596 $task_release = $release;
598 $user_story_release = $release;
601 $us = $this->TrackersAdapter->getUserStories($release);
603 foreach($us as $story) {
604 $stories[$story->getID()] = array(
605 'id' => $story->getID(),
606 'title' => $story->getSummary(),
607 'description' => str_replace("\n", '<br>', $story->getDetails()),
608 'priority' => $story->getPriority(),
610 'url' => $this->TrackersAdapter->getTaskUrl($story)
613 if ($user_stories_sort_extra_field_id) {
614 $efd = $story ->getExtraFieldData();
615 $stories[$story->getID()]['order'] = $efd[$user_stories_sort_extra_field_id];
617 //sort by GF priority if another field for sorting is not defined
618 $stories[$story->getID()]['order'] = $stories[$story->getID()]['priority'];
621 if($this->getReleaseFieldTracker() == RELEASE_OF_USER_STORY) {
622 $tasks_trackers = $this->getUsedTrackersData();
623 foreach($tasks_trackers as $tasks_tracker_data) {
624 $tasks = $this->TrackersAdapter->getTasks($tasks_tracker_data['group_artifact_id'], $assigned_to, NULL, $story->getID());
625 foreach($tasks as $task) {
626 $task_maped = $this->getMappedTask($task);
627 $stories[$story->getID()]['tasks'][] = $task_maped;
633 if ($this->getReleaseFieldTracker() == RELEASE_OF_TASK) {
634 $tasks_trackers = $this->getUsedTrackersData();
635 foreach($tasks_trackers as $tasks_tracker_data) {
636 $tasks = $this->TrackersAdapter->getTasks($tasks_tracker_data['group_artifact_id'], $assigned_to, $task_release);
637 foreach($tasks as $task) {
638 $task_maped = $this->getMappedTask($task);
639 $stories[intval($task_maped['user_story'])]['tasks'][] = $task_maped;
644 $but = array_values($stories);
646 //leave only stories, having not empty tasks list
647 $ret_stories = array();
648 foreach($but as $us) {
649 if (count($us['tasks']) > 0 ) {
650 $ret_stories[] = $us;
654 usort($ret_stories, array($this, 'sortUserStories'));
660 * getMappedTask - map artifact object into hash and add column and presentation specific fields
662 * @param Artifact artifact instance
666 function getMappedTask($task) {
667 static $_used_trackers_data = NULL;
668 static $_first_column_id = NULL;
670 if (!$_used_trackers_data) {
671 foreach($this->getUsedTrackersData() as $tasks_tracker_data) {
672 $_used_trackers_data[ $tasks_tracker_data['group_artifact_id'] ] = $tasks_tracker_data;
676 $task_maped = $this->_mapTask($task);
677 $column = taskboard_column_get_object_by_resolution($this, $task_maped['resolution']);
679 $task_maped['phase_id'] = $column->getID();
681 if($this->getFirstColumnByDefault()) {
682 if(!$_first_column_id) {
683 $columns = $this->getColumns();
684 $_first_column_id = $columns[0]->getID();
686 $task_maped['phase_id'] = $_first_column_id;
690 $card_title_background = $_used_trackers_data[$task->ArtifactType->getID()]['card_background_color'];
691 if( method_exists($this->TrackersAdapter, 'cardBackgroundColor' ) ) {
692 $task_maped['background'] = $this->TrackersAdapter->cardBackgroundColor($task, $card_title_background );
694 $task_maped['background'] = $card_title_background;
700 function sortUserStories($u1, $u2) {
703 usort( $u1['tasks'], array( $this, 'sortUserStoryTasks' ) );
705 if (!array_key_exists('order', $u1)) {
707 } elseif (!array_key_exists('order', $u2)) {
709 } elseif ($u1['order'] < $u2['order']) {
711 } elseif ($u1['order'] > $u2['order']) {
718 function sortUserStoryTasks($t1, $t2) {
721 if ($t1['priority'] < $t2['priority'] ) {
723 } elseif ( $t1['priority'] > $t2['priority'] ) {
730 function getMandatoryFieldsMapping() {
732 'resolution' => 'resolution',
733 'estimated_dev_effort' => $this->getEstimatedCostField(),
734 'remaining_dev_effort' => $this->getRemainingCostField(),
735 'user_story' => $this->getUserStoriesReferenceField()
740 * _mapTask - map artifact object into hash
742 * @param Artifact artifact instance
746 private function _mapTask($task) {
749 $ef_mapping = $this->getMandatoryFieldsMapping();
751 $fields_ids = $this->TrackersAdapter->getFieldsIds($task->ArtifactType->getID());
752 $extra_data = $task->getExtraFieldDataText();
754 $ret['id'] = $task->getID();
755 $ret['title'] = $task->getSummary();
756 $ret['description'] = str_replace("\n", '<br>', $task->getDetails() );
757 $ret['assigned_to'] = $task->getAssignedRealName();
758 $ret['priority'] = $task->getPriority();
759 foreach( $ef_mapping as $k => $f){
761 if (array_key_exists($f, $fields_ids)) {
762 if (array_key_exists($fields_ids[$f], $extra_data)) {
763 $ret[$k] = $extra_data[$fields_ids[$f]]['value'];
768 if (!$ret['user_story']) {
769 // task is not assigend to any user story
770 $ret['user_story'] = 0;
773 $ret['url'] = $this->TrackersAdapter->getTaskUrl($task);
775 $params = array('user_id' => $task->getAssignedTo(), 'size' => 's', 'content' => '');
776 plugin_hook_by_reference("user_logo", $params);
777 if ($params['content']) {
778 $ret['assigned_to_face'] = $params['content'];
780 $ret['assigned_to_face'] = '';
787 * getColumns - get taskboard columns
791 function getColumns() {
792 $res = db_query_params('SELECT * FROM plugin_taskboard_columns WHERE taskboard_id=$1 ORDER BY order_num', array ($this->getID()));
794 $this->setError(_('Taskboard')._(': ')._('Cannot get list of columns.'));
799 while($row = db_fetch_array($res)) {
800 $columns[] = new TaskBoardColumn($this, $row);
802 db_free_result($res);
807 * addColumn - add taskboard column
811 function addColumn($title, $title_bg_color, $column_bg_color, $max_tasks) {
814 $res = db_query_params('SELECT COUNT(*) as count FROM plugin_taskboard_columns WHERE taskboard_id=$1', array ($this->getID()));
819 $row = db_fetch_array($res);
820 $order = intval($row['count']) + 1;
821 db_free_result($res);
823 $res = db_query_params(
824 'INSERT INTO plugin_taskboard_columns(taskboard_id, title, title_background_color, column_background_color, max_tasks, order_num) VALUES($1,$2,$3,$4,$5,$6)',
837 $column_id = db_insertid($res, 'plugin_taskboard_columns', 'taskboard_column_id');
838 db_free_result($res);
844 * getExtraFields - get a list of extra fields, existing is all used task trackers
846 * @param array list of allowed extra fields types
847 * @param array list of excluded aliases
849 * @return array array of aliases
851 function getExtraFields($allowed_types = array(), $used_trackers = NULL, $excluded_aliases = array('resolution')) {
852 $atf = $this->TrackersAdapter->getArtifactTypeFactory();
853 if (!$atf || !is_object($atf) || $atf->isError()) {
854 return _('Could Not Get ArtifactTypeFactory');
857 if (!$used_trackers) {
858 $used_trackers = $this->getUsedTrackersIds();
861 $common_fields = array();
863 foreach ($allowed_types as $allowed_type) {
864 $common_fields[$allowed_type] = array();
867 $at_arr = $atf->getArtifactTypes();
869 for ($j = 0; $j < count($at_arr); $j++) {
870 if (!is_object($at_arr[$j])) {
872 } elseif ($at_arr[$j]->isError()) {
873 return $at_arr[$j]->getErrorMessage();
875 $tracker_id = $at_arr[$j]->getID();
877 if (in_array($tracker_id, $used_trackers)) {
878 // select common fields for the give types
879 $fields = $at_arr[$j]->getExtraFields($allowed_types);
881 foreach ($allowed_types as $allowed_type) {
882 $tmp[$allowed_type] = array();
885 foreach ($fields as $field) {
886 // exclude 'resolution' field
887 if (!in_array($field['alias'],$excluded_aliases)) {
889 if (in_array($field['field_type'], $allowed_types)) {
890 $tmp[$field['field_type']][$field['alias']] = $field['field_name'];
893 in_array($field['alias'], array_keys($common_fields[$field['field_type']])) &&
894 in_array($field['field_type'], $allowed_types)
896 $tmp[$field['field_type']][$field['alias']] = $field['field_name'];
900 $common_fields = $tmp;
905 return $common_fields;
909 * getExtraFieldValues - get hash of values, available for the given extra field
911 * @param string extra field alias
913 * @return array hash element_name => element_id
915 function getExtraFieldValues($extra_field_alias) {
918 $tasks_trackers = $this->getUsedTrackersIds();
919 foreach($tasks_trackers as $tracker_id) {
920 $ef_values = $this->TrackersAdapter->getExtraFieldValues($tracker_id, $extra_field_alias);
921 if (count($ret) == 0) {
925 foreach($ret as $name => $id) {
926 if( array_key_exists($name, $ef_values)) {
938 * getReleases - get taskboard releases
942 function getReleases() {
943 $res = db_query_params('SELECT * FROM plugin_taskboard_releases WHERE taskboard_id = $1 ORDER BY start_date, end_date', array($this->getID()));
945 $this->setError(_('Taskboard')._(': ')._('Cannot get list of releases.'));
950 while( $row = db_fetch_array($res)) {
951 $releases[] = new TaskBoardRelease($this, $row);
953 db_free_result($res);
958 * getCurrentRelease - get current or the most recent release object
962 function getCurrentRelease() {
963 $current_release = NULL;
965 $res = db_query_params (
966 'SELECT * FROM plugin_taskboard_releases WHERE taskboard_id=$1 AND start_date < $2 ORDER BY start_date DESC LIMIT 1',
969 strtotime(date('Y-m-d'))
973 $this->setError(_('Taskboard')._(': ')._('Cannot get current release.'));
976 $row = db_fetch_array($res);
978 $current_release = new TaskBoardRelease($this, $row);
981 db_free_result($res);
983 return $current_release;
987 * getReleaseValues - get list of all available reslease values
991 function getReleaseValues() {
994 if ($this->getReleaseFieldTracker() == 1) {
995 // get values from tasks trackers
996 $ret = $this->getExtraFieldValues($this->getReleaseField());
998 // get values from user stories trackers
999 $ret = $this->TrackersAdapter->getExtraFieldValues($this->getUserStoriesTrackerID(), $this->getReleaseField());
1006 * getAvailableResolutions - get list of all available resolution values
1010 function getAvailableResolutions() {
1011 return array_keys($this->getExtraFieldValues('resolution'));
1015 * getUsedResolutions - get list of resolutions that are already used with taskboard columns
1019 function getUsedResolutions() {
1020 $res = db_query_params(
1021 'SELECT R.* FROM plugin_taskboard_columns_resolutions as R, plugin_taskboard_columns as C
1022 WHERE C.taskboard_id=$1 AND R.taskboard_column_id=C.taskboard_column_id',
1023 array($this->getID())
1026 $this->setError(_('Taskboard')._(': ')._('Cannot get used resolutions'));
1030 $resolutions= array();
1031 while($row = db_fetch_array($res)) {
1032 $resolutions[$row['taskboard_column_resolution']] = $row['taskboard_column_resolution'];
1034 db_free_result($res);
1036 return array_keys($resolutions);
1040 * getUnusedResolutions - get list of resolutions that are not used with taskboard columns
1044 function getUnusedResolutions() {
1045 static $resolutions = NULL;
1047 if( !$resolutions ) {
1048 $all_resolutions = $this->getAvailableResolutions();
1049 $used_resolutions = $this->getUsedResolutions();
1051 $resolutions = array();
1052 if( $all_resolutions && count( $used_resolutions ) > 0 ) {
1053 $resolutions = array_diff( $all_resolutions, $used_resolutions );
1055 $resolutions = $all_resolutions;
1059 return $resolutions;