function index()
 {
     parent::index();
     $milestones_t = Milestones::findAllByProject($this->active_project);
     $tasks_t = Tasks::findByProject($this->active_project, $this->logged_user);
     $milestones = array();
     $tasks = array();
     // voglio il task non categorizzato che inizia prima di tutti, quindi setto questo nel futuro
     $first_task_time = new DateValue(time() + time());
     $trovato = false;
     if (is_foreachable($tasks_t)) {
         foreach ($tasks_t as $task) {
             $res = array();
             $res['id'] = $task->getTaskId();
             $res['name'] = $task->getName();
             $task->complete()->describe($this->logged_user, true, true, $completion_description);
             $task_description = $task->describe($this->logged_user, true, true);
             $res['is_completed'] = $completion_description['is_completed'];
             $res['completed_on'] = $completion_description['completed_on'];
             $res['due_on'] = $completion_description['due_on'];
             // non è sempre settato
             $res['milestone_id'] = $task_description['milestone_id'] ? $task_description['milestone_id'] : 0;
             $res['created_on_d'] = $task->getCreatedOn()->getDay();
             $res['created_on_m'] = $task->getCreatedOn()->getMonth() - 1;
             $res['created_on_y'] = $task->getCreatedOn()->getYear();
             // La data di inizio non è sempre presente. Quindi se non c'è, prendo la data di creazione del task.
             // Inoltre questo campo dipende dal modulo TaskPlus
             if (AngieApplication::isModuleLoaded('tasks_plus') && TaskPlus::getStartOn($task)) {
                 $start_on = TaskPlus::getStartOn($task);
             } else {
                 $start_on = $task->getCreatedOn();
             }
             $res['start_on_d'] = $start_on->getDay();
             $res['start_on_m'] = $start_on->getMonth() - 1;
             //javascript merda parte da Gennaio = 0
             $res['start_on_y'] = $start_on->getYear();
             // giorni in più
             $days = 60 * 60 * 24 * 15;
             //15 giorni in più
             if ($completion_description['is_completed']) {
                 $completion_date = $completion_description['completed_on'];
             } else {
                 if ($completion_description['due_on']) {
                     // non è completata ma ha data di fine settata
                     $completion_date = $completion_description['due_on'];
                 } else {
                     if (!$completion_description['due_on']) {
                         // non è completata e non ha data di fine settata
                         $completion_date = $start_on->advance($days, false);
                         // (data_inizio || data_creazione) + 15 giorni
                     }
                 }
             }
             $res['finish_on_d'] = $completion_date->getDay();
             $res['finish_on_m'] = $completion_date->getMonth() - 1;
             //javascript merda parte da Gennaio = 0
             $res['finish_on_y'] = $completion_date->getYear();
             $res['durata'] = $start_on->daysBetween($completion_date) * 8;
             //giorni_differenza * ore_lavorative
             if ($res['is_completed']) {
                 $res['percent_completion'] = 100;
             } else {
                 list($total_subtasks, $open_subtasks) = ProjectProgress::getObjectProgress($task);
                 $completed_subtasks = $total_subtasks - $open_subtasks;
                 if ($open_subtasks) {
                     $res['percent_completion'] = ceil($completed_subtasks / $total_subtasks * 100);
                 } else {
                     $res['percent_completion'] = 0;
                 }
             }
             $tasks[] = $res;
             if ($res['milestone_id'] == 0 && $first_task_time->getTimestamp() > $start_on->getTimestamp()) {
                 $first_task_time = $start_on;
                 $trovato = false;
             }
         }
     }
     if ($trovato) {
         //Aggiungo la milestone per tasks non categorizzati
         $milestones[0]['id'] = 0;
         $milestones[0]['name'] = lang("Uncategorized");
         $milestones[0]['start_on_d'] = $first_task_time->getDay();
         $milestones[0]['start_on_m'] = $first_task_time->getMonth() - 1;
         $milestones[0]['start_on_y'] = $first_task_time->getYear();
         $milestones[0]['durata'] = 1;
     }
     if (is_foreachable($milestones_t)) {
         foreach ($milestones_t as $milestone) {
             $res = array();
             $res['id'] = $milestone->getId();
             $res['name'] = $milestone->getName();
             $res['start_on_d'] = $milestone->getStartOn()->getDay();
             $res['start_on_m'] = $milestone->getStartOn()->getMonth() - 1;
             //javascript merda parte da Gennaio = 0
             $res['start_on_y'] = $milestone->getStartOn()->getYear();
             $res['durata'] = ($milestone->getDueOn()->getTimestamp() - $milestone->getStartOn()->getTimestamp()) / (60 * 60 * 24) * 8;
             //giorni * ore lavorative
             $milestones[] = $res;
         }
     }
     $this->smarty->assign(array('milestones' => $milestones, 'tasks' => $tasks));
 }
 /**
  * Export project milestones
  *
  * @param void
  * @return null
  */
 function export()
 {
     $object_visibility = array_var($_GET, 'visibility', VISIBILITY_NORMAL);
     $exportable_modules = explode(',', array_var($_GET, 'modules', null));
     if (!is_foreachable($exportable_modules)) {
         $exportable_modules = null;
     }
     // if
     require_once PROJECT_EXPORTER_MODULE_PATH . '/models/ProjectExporterOutputBuilder.class.php';
     $output_builder = new ProjectExporterOutputBuilder($this->active_project, $this->smarty, $this->active_module, $exportable_modules);
     if (!$output_builder->createOutputFolder()) {
         $this->serveData($output_builder->execution_log, 'execution_log', null, FORMAT_JSON);
     }
     // if
     $output_builder->createAttachmentsFolder();
     $active_milestones = array();
     $completed_milestones = array();
     $all_milestones = Milestones::findAllByProject($this->active_project, $object_visibility);
     if (is_foreachable($all_milestones)) {
         $output_builder->setFileTemplate(MILESTONES_MODULE, 'milestones', 'object');
         foreach ($all_milestones as $milestone) {
             if ($milestone->isCompleted()) {
                 $completed_milestones[] = $milestone;
             } else {
                 $active_milestones[] = $milestone;
             }
             // if
             // Build milestone details page
             $objects = array();
             event_trigger('on_milestone_objects_by_visibility', array(&$milestone, &$objects, $object_visibility));
             $total_objects = 0;
             if (is_foreachable($objects)) {
                 foreach ($objects as $objects_per_module) {
                     $total_objects += count($objects_per_module);
                 }
                 // foreach
             }
             // if
             $output_builder->smarty->assign(array('active_milestone' => $milestone, 'active_milestone_objects' => $objects, 'total_objects' => $total_objects));
             $output_builder->outputToFile('milestone_' . $milestone->getId());
         }
         // foreach
     }
     // if
     // export milestones front page
     $output_builder->setFileTemplate(MILESTONES_MODULE, 'milestones', 'index');
     $output_builder->smarty->assign('active_milestones', $active_milestones);
     $output_builder->smarty->assign('completed_milestones', $completed_milestones);
     $output_builder->outputToFile('index');
     $this->serveData($output_builder->execution_log, 'execution_log', null, FORMAT_JSON);
 }
 /**
  * Copy project items into a destination project
  *
  * @param Project $to
  * @return null
  */
 function copyItems(&$to)
 {
     // Prepare time diff
     $source_starts_on = $this->getStartsOn();
     if (!instance_of($source_starts_on, 'DateValue')) {
         $source_starts_on = $this->getCreatedOn();
     }
     // if
     $target_starts_on = $to->getStartsOn();
     if (!instance_of($target_starts_on, 'DateValue')) {
         $target_starts_on = $to->getCreatedOn();
     }
     // if
     $diff = $target_starts_on->getTimestamp() - $source_starts_on->getTimestamp();
     // Migrate project users
     $project_users = ProjectUsers::findByProject($this);
     if (is_foreachable($project_users)) {
         foreach ($project_users as $project_user) {
             if ($to->getLeaderId() != $project_user->getUserId()) {
                 $user = $project_user->getUser();
                 if (instance_of($user, 'User')) {
                     $to->addUser($user, $project_user->getRole(), $project_user->getPermissions());
                 }
                 // if
             }
             // if
         }
         // foreach
     }
     // if
     // We need to move milestones in order to get milestones map
     $milestones_map = null;
     $milestones = Milestones::findAllByProject($this, VISIBILITY_PRIVATE);
     if (is_foreachable($milestones)) {
         $milestones_map = array();
         foreach ($milestones as $milestone) {
             $copied_milestone = $milestone->copyToProject($to);
             if (instance_of($copied_milestone, 'Milestone')) {
                 $copied_milestone->advance($diff, true);
                 $milestones_map[$milestone->getId()] = $copied_milestone;
             }
             // if
         }
         // foreach
     }
     // if
     // Now move categories
     $categories_map = null;
     $categories = Categories::findByProject($this);
     if (is_foreachable($categories)) {
         foreach ($categories as $category) {
             $copied_category = $category->copyToProject($to, null, null, false);
             if (instance_of($copied_category, 'Category')) {
                 $categories_map[$category->getId()] = $copied_category;
             }
             // if
         }
         // foreach
     }
     // if
     // Let the modules to their thing
     event_trigger('on_copy_project_items', array(&$this, &$to, $milestones_map, $categories_map));
     // Now, lets update due dates
     $completable_types = get_completable_project_object_types();
     if (is_foreachable($completable_types)) {
         foreach ($completable_types as $k => $type) {
             if (strtolower($type) == 'milestone') {
                 unset($completable_types[$k]);
             }
             // if
         }
         // foreach
         if (count($completable_types) > 0) {
             $rows = db_execute_all('SELECT id, due_on FROM ' . TABLE_PREFIX . 'project_objects WHERE project_id = ? AND type IN (?) AND due_on IS NOT NULL', $to->getId(), $completable_types);
             if (is_foreachable($rows)) {
                 foreach ($rows as $row) {
                     $id = (int) $row['id'];
                     $new_date = date(DATE_MYSQL, strtotime($row['due_on']) + $diff);
                     db_execute('UPDATE ' . TABLE_PREFIX . 'project_objects SET due_on = ? WHERE id = ?', $new_date, $id);
                     cache_remove("acx_project_objects_id_{$id}");
                 }
                 // foreach
             }
             // if
         }
         // if
     }
     // if
     // Refresh tasks count, just in case...
     $to->refreshTasksCount();
 }