public function processIncomingEmailAccount(IncomingEmailAccount $account) { $count = 0; if ($emails = $account->getUnprocessedEmails()) { try { $current_user = framework\Context::getUser(); foreach ($emails as $email) { $user = $this->getOrCreateUserFromEmailString($email->from); if ($user instanceof User) { if (framework\Context::getUser()->getID() != $user->getID()) { framework\Context::switchUserContext($user); } $message = $account->getMessage($email); $data = $message->getBodyPlain() ? $message->getBodyPlain() : strip_tags($message->getBodyHTML()); if ($data) { if (mb_detect_encoding($data, 'UTF-8', true) === false) { $data = utf8_encode($data); } $new_data = ''; foreach (explode("\n", $data) as $line) { $line = trim($line); if ($line) { $line = preg_replace('/^(_{2,}|-{2,})$/', "<hr>", $line); $new_data .= $line . "\n"; } else { $new_data .= "\n"; } } $data = nl2br($new_data, false); } // Parse the subject, and obtain the issues. $parsed_commit = Issue::getIssuesFromTextByRegex(mb_decode_mimeheader($email->subject)); $issues = $parsed_commit["issues"]; // If any issues were found, add new comment to each issue. if ($issues) { foreach ($issues as $issue) { $text = preg_replace('#(^\\w.+:\\n)?(^>.*(\\n|$))+#mi', "", $data); $text = trim($text); if (!$this->processIncomingEmailCommand($text, $issue) && $user->canPostComments()) { $comment = new Comment(); $comment->setContent($text); $comment->setPostedBy($user); $comment->setTargetID($issue->getID()); $comment->setTargetType(Comment::TYPE_ISSUE); $comment->save(); } } } else { if ($user->canReportIssues($account->getProject())) { $issue = new Issue(); $issue->setProject($account->getProject()); $issue->setTitle(mb_decode_mimeheader($email->subject)); $issue->setDescription($data); $issue->setPostedBy($user); $issue->setIssuetype($account->getIssuetype()); $issue->save(); // Append the new issue to the list of affected issues. This // is necessary in order to process the attachments properly. $issues[] = $issue; } } // If there was at least a single affected issue, and mail // contains attachments, add those attachments to related issues. if ($issues && $message->hasAttachments()) { foreach ($message->getAttachments() as $attachment_no => $attachment) { echo 'saving attachment ' . $attachment_no; $name = $attachment['filename']; $new_filename = framework\Context::getUser()->getID() . '_' . NOW . '_' . basename($name); if (framework\Settings::getUploadStorage() == 'files') { $files_dir = framework\Settings::getUploadsLocalpath(); $filename = $files_dir . $new_filename; } else { $filename = $name; } Logging::log('Creating issue attachment ' . $filename . ' from attachment ' . $attachment_no); echo 'Creating issue attachment ' . $filename . ' from attachment ' . $attachment_no; $content_type = $attachment['type'] . '/' . $attachment['subtype']; $file = new File(); $file->setRealFilename($new_filename); $file->setOriginalFilename(basename($name)); $file->setContentType($content_type); $file->setDescription($name); $file->setUploadedBy(framework\Context::getUser()); if (framework\Settings::getUploadStorage() == 'database') { $file->setContent($attachment['data']); } else { Logging::log('Saving file ' . $new_filename . ' with content from attachment ' . $attachment_no); file_put_contents($new_filename, $attachment['data']); } $file->save(); // Attach file to each related issue. foreach ($issues as $issue) { $issue->attachFile($file); } } } $count++; } } } catch (\Exception $e) { } if (framework\Context::getUser()->getID() != $current_user->getID()) { framework\Context::switchUserContext($current_user); } } $account->setTimeLastFetched(time()); $account->setNumberOfEmailsLastFetched($count); $account->save(); return $count; }
/** * Adds an epic * * @Route(url="/boards/:board_id/addepic") * * @param framework\Request $request */ public function runAddEpic(framework\Request $request) { $this->forward403unless($this->_checkProjectPageAccess('project_planning')); $board = entities\tables\AgileBoards::getTable()->selectById($request['board_id']); try { $title = trim($request['title']); $shortname = trim($request['shortname']); if (!$title) { throw new \Exception($this->getI18n()->__('You have to provide a title')); } if (!$shortname) { throw new \Exception($this->getI18n()->__('You have to provide a label')); } $issue = new \thebuggenie\core\entities\Issue(); $issue->setTitle($title); $issue->setShortname($shortname); $issue->setIssuetype($board->getEpicIssuetypeID()); $issue->setProject($board->getProject()); $issue->setPostedBy($this->getUser()); $issue->save(); return $this->renderJSON(array('issue_details' => $issue->toJSON())); } catch (\Exception $e) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('error' => $e->getMessage())); } }
protected function _postIssue() { $fields_array = $this->selected_project->getReportableFieldsArray($this->issuetype_id); $issue = new entities\Issue(); $issue->setTitle($this->title); $issue->setIssuetype($this->issuetype_id); $issue->setProject($this->selected_project); if (isset($fields_array['shortname'])) { $issue->setShortname($this->selected_shortname); } if (isset($fields_array['description'])) { $issue->setDescription($this->selected_description); $issue->setDescriptionSyntax($this->selected_description_syntax); } if (isset($fields_array['reproduction_steps'])) { $issue->setReproductionSteps($this->selected_reproduction_steps); $issue->setReproductionStepsSyntax($this->selected_reproduction_steps_syntax); } if (isset($fields_array['category']) && $this->selected_category instanceof entities\Datatype) { $issue->setCategory($this->selected_category->getID()); } if (isset($fields_array['status']) && $this->selected_status instanceof entities\Datatype) { $issue->setStatus($this->selected_status->getID()); } if (isset($fields_array['reproducability']) && $this->selected_reproducability instanceof entities\Datatype) { $issue->setReproducability($this->selected_reproducability->getID()); } if (isset($fields_array['resolution']) && $this->selected_resolution instanceof entities\Datatype) { $issue->setResolution($this->selected_resolution->getID()); } if (isset($fields_array['severity']) && $this->selected_severity instanceof entities\Datatype) { $issue->setSeverity($this->selected_severity->getID()); } if (isset($fields_array['priority']) && $this->selected_priority instanceof entities\Datatype) { $issue->setPriority($this->selected_priority->getID()); } if (isset($fields_array['estimated_time'])) { $issue->setEstimatedTime($this->selected_estimated_time); } if (isset($fields_array['spent_time'])) { $issue->setSpentTime($this->selected_spent_time); } if (isset($fields_array['milestone']) || isset($this->selected_milestone)) { $issue->setMilestone($this->selected_milestone); } if (isset($fields_array['percent_complete'])) { $issue->setPercentCompleted($this->selected_percent_complete); } if (isset($fields_array['pain_bug_type'])) { $issue->setPainBugType($this->selected_pain_bug_type); } if (isset($fields_array['pain_likelihood'])) { $issue->setPainLikelihood($this->selected_pain_likelihood); } if (isset($fields_array['pain_effect'])) { $issue->setPainEffect($this->selected_pain_effect); } foreach (entities\CustomDatatype::getAll() as $customdatatype) { if (!isset($fields_array[$customdatatype->getKey()])) { continue; } if ($customdatatype->hasCustomOptions()) { if (isset($fields_array[$customdatatype->getKey()]) && $this->selected_customdatatype[$customdatatype->getKey()] instanceof entities\CustomDatatypeOption) { $selected_option = $this->selected_customdatatype[$customdatatype->getKey()]; $issue->setCustomField($customdatatype->getKey(), $selected_option->getID()); } } else { $issue->setCustomField($customdatatype->getKey(), $this->selected_customdatatype[$customdatatype->getKey()]); } } // FIXME: If we set the issue assignee during report issue, this needs to be set INSTEAD of this if ($this->selected_project->canAutoassign()) { if (isset($fields_array['component']) && $this->selected_component instanceof entities\Component && $this->selected_component->hasLeader()) { $issue->setAssignee($this->selected_component->getLeader()); } elseif (isset($fields_array['edition']) && $this->selected_edition instanceof entities\Edition && $this->selected_edition->hasLeader()) { $issue->setAssignee($this->selected_edition->getLeader()); } elseif ($this->selected_project->hasLeader()) { $issue->setAssignee($this->selected_project->getLeader()); } } $issue->save(); if (isset($this->parent_issue)) { $issue->addParentIssue($this->parent_issue); } if (isset($fields_array['edition']) && $this->selected_edition instanceof entities\Edition) { $issue->addAffectedEdition($this->selected_edition); } if (isset($fields_array['build']) && $this->selected_build instanceof entities\Build) { $issue->addAffectedBuild($this->selected_build); } if (isset($fields_array['component']) && $this->selected_component instanceof entities\Component) { $issue->addAffectedComponent($this->selected_component); } return $issue; }
protected function _postIssue(framework\Request $request) { $fields_array = $this->selected_project->getReportableFieldsArray($this->issuetype_id); $issue = new entities\Issue(); $issue->setTitle($this->title); $issue->setIssuetype($this->issuetype_id); $issue->setProject($this->selected_project); if (isset($fields_array['shortname'])) { $issue->setShortname($this->selected_shortname); } if (isset($fields_array['description'])) { $issue->setDescription($this->selected_description); $issue->setDescriptionSyntax($this->selected_description_syntax); } if (isset($fields_array['reproduction_steps'])) { $issue->setReproductionSteps($this->selected_reproduction_steps); $issue->setReproductionStepsSyntax($this->selected_reproduction_steps_syntax); } if (isset($fields_array['category']) && $this->selected_category instanceof entities\Datatype) { $issue->setCategory($this->selected_category->getID()); } if (isset($fields_array['status']) && $this->selected_status instanceof entities\Datatype) { $issue->setStatus($this->selected_status->getID()); } if (isset($fields_array['reproducability']) && $this->selected_reproducability instanceof entities\Datatype) { $issue->setReproducability($this->selected_reproducability->getID()); } if (isset($fields_array['resolution']) && $this->selected_resolution instanceof entities\Datatype) { $issue->setResolution($this->selected_resolution->getID()); } if (isset($fields_array['severity']) && $this->selected_severity instanceof entities\Datatype) { $issue->setSeverity($this->selected_severity->getID()); } if (isset($fields_array['priority']) && $this->selected_priority instanceof entities\Datatype) { $issue->setPriority($this->selected_priority->getID()); } if (isset($fields_array['estimated_time'])) { $issue->setEstimatedTime($this->selected_estimated_time); } if (isset($fields_array['spent_time'])) { $issue->setSpentTime($this->selected_spent_time); } if (isset($fields_array['milestone']) || isset($this->selected_milestone)) { $issue->setMilestone($this->selected_milestone); } if (isset($fields_array['percent_complete'])) { $issue->setPercentCompleted($this->selected_percent_complete); } if (isset($fields_array['pain_bug_type'])) { $issue->setPainBugType($this->selected_pain_bug_type); } if (isset($fields_array['pain_likelihood'])) { $issue->setPainLikelihood($this->selected_pain_likelihood); } if (isset($fields_array['pain_effect'])) { $issue->setPainEffect($this->selected_pain_effect); } foreach (entities\CustomDatatype::getAll() as $customdatatype) { if (!isset($fields_array[$customdatatype->getKey()])) { continue; } if ($customdatatype->hasCustomOptions()) { if (isset($fields_array[$customdatatype->getKey()]) && $this->selected_customdatatype[$customdatatype->getKey()] instanceof entities\CustomDatatypeOption) { $selected_option = $this->selected_customdatatype[$customdatatype->getKey()]; $issue->setCustomField($customdatatype->getKey(), $selected_option->getID()); } } else { $issue->setCustomField($customdatatype->getKey(), $this->selected_customdatatype[$customdatatype->getKey()]); } } // FIXME: If we set the issue assignee during report issue, this needs to be set INSTEAD of this if ($this->selected_project->canAutoassign()) { if (isset($fields_array['component']) && $this->selected_component instanceof entities\Component && $this->selected_component->hasLeader()) { $issue->setAssignee($this->selected_component->getLeader()); } elseif (isset($fields_array['edition']) && $this->selected_edition instanceof entities\Edition && $this->selected_edition->hasLeader()) { $issue->setAssignee($this->selected_edition->getLeader()); } elseif ($this->selected_project->hasLeader()) { $issue->setAssignee($this->selected_project->getLeader()); } } if ($request->hasParameter('custom_issue_access') && $this->selected_project->permissionCheck('canlockandeditlockedissues')) { switch ($request->getParameter('issue_access')) { case 'public': case 'public_category': $issue->setLocked(false); $issue->setLockedCategory($request->hasParameter('public_category')); break; case 'restricted': $issue->setLocked(); break; } } else { $issue->setLockedFromProject($this->selected_project); } framework\Event::listen('core', 'thebuggenie\\core\\entities\\Issue::createNew_pre_notifications', array($this, 'listen_issueCreate')); $issue->save(); if (isset($this->parent_issue)) { $issue->addParentIssue($this->parent_issue); } if (isset($fields_array['edition']) && $this->selected_edition instanceof entities\Edition) { $issue->addAffectedEdition($this->selected_edition); } if (isset($fields_array['build']) && $this->selected_build instanceof entities\Build) { $issue->addAffectedBuild($this->selected_build); } if (isset($fields_array['component']) && $this->selected_component instanceof entities\Component) { $issue->addAffectedComponent($this->selected_component); } return $issue; }
public function runDoImportCSV(framework\Request $request) { try { if ($request['csv_data'] == '') { throw new \Exception($this->getI18n()->__('No data supplied to import')); } $csv = str_replace("\r\n", "\n", $request['csv_data']); $csv = html_entity_decode($csv); $headerrow = null; $data = array(); $errors = array(); // Parse CSV $handle = fopen("php://memory", 'r+'); fputs($handle, $csv); rewind($handle); $i = 0; while (($row = fgetcsv($handle, 1000)) !== false) { if (!$headerrow) { $headerrow = $row; } else { if (count($headerrow) == count($row)) { $data[] = array_combine($headerrow, $row); } else { $errors[] = $this->getI18n()->__('Row %row does not have the same number of elements as the header row', array('%row' => $i)); } } $i++; } fclose($handle); if (empty($data)) { throw new \Exception($this->getI18n()->__('Insufficient data to import')); } // Verify required columns are present based on type $requiredcols = array(self::CSV_TYPE_CLIENTS => array(self::CSV_CLIENT_NAME), self::CSV_TYPE_PROJECTS => array(self::CSV_PROJECT_NAME), self::CSV_TYPE_ISSUES => array(self::CSV_ISSUE_TITLE, self::CSV_ISSUE_PROJECT, self::CSV_ISSUE_ISSUE_TYPE)); if (!isset($requiredcols[$request['type']])) { throw new \Exception('Sorry, this type is unimplemented'); } foreach ($requiredcols[$request['type']] as $col) { if (!in_array($col, $headerrow)) { $errors[] = $this->getI18n()->__('Required column \'%col\' not found in header row', array('%col' => $col)); } } // Check if rows are long enough and fields are not empty for ($i = 0; $i != count($data); $i++) { $activerow = $data[$i]; // Check if fields are empty foreach ($activerow as $col => $val) { if (strlen($val) == 0) { $errors[] = $this->getI18n()->__('Row %row column %col has no value', array('%col' => $col, '%row' => $i + 1)); } } } if (count($errors) == 0) { // Check if fields are valid switch ($request['type']) { case self::CSV_TYPE_PROJECTS: for ($i = 0; $i != count($data); $i++) { $activerow = $data[$i]; // Check if project exists $key = str_replace(' ', '', $activerow[self::CSV_PROJECT_NAME]); $key = mb_strtolower($key); $tmp = entities\Project::getByKey($key); if ($tmp !== null) { $errors[] = $this->getI18n()->__('Row %row: A project with this name already exists', array('%row' => $i + 1)); } // First off are booleans $boolitems = array(self::CSV_PROJECT_SCRUM, self::CSV_PROJECT_ALLOW_REPORTING, self::CSV_PROJECT_AUTOASSIGN, self::CSV_PROJECT_FREELANCE, self::CSV_PROJECT_EN_BUILDS, self::CSV_PROJECT_EN_COMPS, self::CSV_PROJECT_EN_EDITIONS, self::CSV_PROJECT_SHOW_SUMMARY); foreach ($boolitems as $boolitem) { if (array_key_exists($boolitem, $activerow) && isset($activerow[$boolitem]) && $activerow[$boolitem] != 1 && $activerow[$boolitem] != 0) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be 1/0)', array('%col' => $boolitem, '%row' => $i + 1)); } } // Now identifiables $identifiableitems = array(array(self::CSV_PROJECT_QA, self::CSV_PROJECT_QA_TYPE), array(self::CSV_PROJECT_LEAD, self::CSV_PROJECT_LEAD_TYPE), array(self::CSV_PROJECT_OWNER, self::CSV_PROJECT_OWNER_TYPE)); foreach ($identifiableitems as $identifiableitem) { if (!array_key_exists($identifiableitem[1], $activerow) && array_key_exists($identifiableitem[0], $activerow) || array_key_exists($identifiableitem[1], $activerow) && !array_key_exists($identifiableitem[0], $activerow)) { $errors[] = $this->getI18n()->__('Row %row: Both the type and item ID must be supplied for owner/lead/qa fields', array('%row' => $i + 1)); continue; } if (array_key_exists($identifiableitem[1], $activerow) && isset($activerow[$identifiableitem[1]]) !== null && $activerow[$identifiableitem[1]] != self::CSV_IDENTIFIER_TYPE_USER && $activerow[$identifiableitem[1]] != self::CSV_IDENTIFIER_TYPE_TEAM) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be 1 for a user or 2 for a team)', array('%col' => $identifiableitem[1], '%row' => $i + 1)); } if (array_key_exists($identifiableitem[0], $activerow) && isset($activerow[$identifiableitem[0]]) && !is_numeric($activerow[$identifiableitem[0]])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => $identifiableitem[0], '%row' => $i + 1)); } elseif (array_key_exists($identifiableitem[0], $activerow) && isset($activerow[$identifiableitem[0]]) && is_numeric($activerow[$identifiableitem[0]])) { // check if they exist switch ($activerow[$identifiableitem[1]]) { case self::CSV_IDENTIFIER_TYPE_USER: try { entities\User::getB2DBTable()->selectByID($activerow[$identifiableitem[0]]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: user does not exist', array('%col' => $identifiableitem[0], '%row' => $i + 1)); } break; case self::CSV_IDENTIFIER_TYPE_TEAM: try { entities\Team::getB2DBTable()->selectById($activerow[$identifiableitem[0]]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: team does not exist', array('%col' => $identifiableitem[0], '%row' => $i + 1)); } break; } } } // Now check client exists if (array_key_exists(self::CSV_PROJECT_CLIENT, $activerow) && isset($activerow[self::CSV_PROJECT_CLIENT])) { if (!is_numeric($activerow[self::CSV_PROJECT_CLIENT])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_PROJECT_CLIENT, '%row' => $i + 1)); } else { try { entities\Client::getB2DBTable()->selectById($activerow[self::CSV_PROJECT_CLIENT]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: client does not exist', array('%col' => self::CSV_PROJECT_CLIENT, '%row' => $i + 1)); } } } // Now check if workflow exists if (array_key_exists(self::CSV_PROJECT_WORKFLOW_ID, $activerow) && isset($activerow[self::CSV_PROJECT_WORKFLOW_ID])) { if (!is_numeric($activerow[self::CSV_PROJECT_WORKFLOW_ID])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_PROJECT_WORKFLOW_ID, '%row' => $i + 1)); } else { try { entities\WorkflowScheme::getB2DBTable()->selectById($activerow[self::CSV_PROJECT_WORKFLOW_ID]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: workflow scheme does not exist', array('%col' => self::CSV_PROJECT_WORKFLOW_ID, '%row' => $i + 1)); } } } // Now check if issuetype scheme if (array_key_exists(self::CSV_PROJECT_ISSUETYPE_SCHEME, $activerow) && isset($activerow[self::CSV_PROJECT_ISSUETYPE_SCHEME])) { if (!is_numeric($activerow[self::CSV_PROJECT_ISSUETYPE_SCHEME])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_PROJECT_ISSUETYPE_SCHEME, '%row' => $i + 1)); } else { try { entities\IssuetypeScheme::getB2DBTable()->selectById($activerow[self::CSV_PROJECT_ISSUETYPE_SCHEME]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: issuetype scheme does not exist', array('%col' => self::CSV_PROJECT_ISSUETYPE_SCHEME, '%row' => $i + 1)); } } } // Finally check if the summary type is valid. At this point, your error list has probably become so big it has eaten up all your available RAM... if (array_key_exists(self::CSV_PROJECT_SUMMARY_TYPE, $activerow) && isset($activerow[self::CSV_PROJECT_SUMMARY_TYPE])) { if ($activerow[self::CSV_PROJECT_SUMMARY_TYPE] != 'issuetypes' && $activerow[self::CSV_PROJECT_SHOW_SUMMARY] != 'milestones') { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be \'issuetypes\' or \'milestones\')', array('%col' => self::CSV_PROJECT_SUMMARY_TYPE, '%row' => $i + 1)); } } } break; case self::CSV_TYPE_ISSUES: for ($i = 0; $i != count($data); $i++) { $activerow = $data[$i]; // Check if project exists try { $prjtmp = entities\Project::getB2DBTable()->selectByID($activerow[self::CSV_ISSUE_PROJECT]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: Project does not exist', array('%col' => self::CSV_ISSUE_PROJECT, '%row' => $i + 1)); break; } // First off are booleans $boolitems = array(self::CSV_ISSUE_STATE, self::CSV_ISSUE_BLOCKING); foreach ($boolitems as $boolitem) { if (array_key_exists($boolitem, $activerow) && isset($activerow[$boolitem]) && $activerow[$boolitem] != 1 && $activerow[$boolitem] != 0) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be 1/0)', array('%col' => $boolitem, '%row' => $i + 1)); } } // Now numerics $numericitems = array(self::CSV_ISSUE_VOTES, self::CSV_ISSUE_PERCENTAGE, self::CSV_ISSUE_ISSUENO); foreach ($numericitems as $numericitem) { if (array_key_exists($numericitem, $activerow) && isset($activerow[$numericitem]) && !is_numeric($activerow[$numericitem])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => $numericitem, '%row' => $i + 1)); } } // Percentage must be 0-100 if (array_key_exists(self::CSV_ISSUE_PERCENTAGE, $activerow) && isset($activerow[self::CSV_ISSUE_PERCENTAGE]) && ($activerow[self::CSV_ISSUE_PERCENTAGE] < 0 || $activerow[self::CSV_ISSUE_PERCENTAGE] > 100)) { $errors[] = $this->getI18n()->__('Row %row column %col: Percentage must be from 0 to 100 inclusive', array('%col' => self::CSV_ISSUE_PERCENTAGE, '%row' => $i + 1)); } // Now identifiables $identifiableitems = array(array(self::CSV_ISSUE_OWNER, self::CSV_ISSUE_OWNER_TYPE), array(self::CSV_ISSUE_ASSIGNED, self::CSV_ISSUE_ASSIGNED_TYPE)); foreach ($identifiableitems as $identifiableitem) { if (!array_key_exists($identifiableitem[1], $activerow) && array_key_exists($identifiableitem[0], $activerow) || array_key_exists($identifiableitem[1], $activerow) && !array_key_exists($identifiableitem[0], $activerow)) { $errors[] = $this->getI18n()->__('Row %row: Both the type and item ID must be supplied for owner/lead/qa fields', array('%row' => $i + 1)); continue; } if (array_key_exists($identifiableitem[1], $activerow) && isset($activerow[$identifiableitem[1]]) && $activerow[$identifiableitem[1]] != self::CSV_IDENTIFIER_TYPE_USER && $activerow[$identifiableitem[1]] != self::CSV_IDENTIFIER_TYPE_TEAM) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be 1 for a user or 2 for a team)', array('%col' => $identifiableitem[1], '%row' => $i + 1)); } if (array_key_exists($identifiableitem[0], $activerow) && isset($activerow[$identifiableitem[0]]) && !is_numeric($activerow[$identifiableitem[0]])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => $identifiableitem[0], '%row' => $i + 1)); } elseif (array_key_exists($identifiableitem[0], $activerow) && isset($activerow[$identifiableitem[0]]) && is_numeric($activerow[$identifiableitem[0]])) { // check if they exist switch ($activerow[$identifiableitem[1]]) { case self::CSV_IDENTIFIER_TYPE_USER: try { entities\User::getB2DBTable()->selectByID($activerow[$identifiableitem[0]]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: user does not exist', array('%col' => $identifiableitem[0], '%row' => $i + 1)); } break; case self::CSV_IDENTIFIER_TYPE_TEAM: try { entities\Team::getB2DBTable()->selectById($activerow[$identifiableitem[0]]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: team does not exist', array('%col' => $identifiableitem[0], '%row' => $i + 1)); } break; } } } // Now timestamps if (array_key_exists(self::CSV_ISSUE_POSTED, $activerow) && isset($activerow[self::CSV_ISSUE_POSTED]) && (string) (int) $activerow[self::CSV_ISSUE_POSTED] !== $activerow[self::CSV_ISSUE_POSTED] && $activerow[self::CSV_ISSUE_POSTED] >= PHP_INT_MAX && $activerow[self::CSV_ISSUE_POSTED] <= ~PHP_INT_MAX) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a Unix timestamp)', array('%col' => self::CSV_ISSUE_POSTED, '%row' => $i + 1)); } // Now check user exists for postedby if (array_key_exists(self::CSV_ISSUE_POSTED_BY, $activerow) && isset($activerow[self::CSV_ISSUE_POSTED_BY])) { if (!is_numeric($activerow[self::CSV_ISSUE_POSTED_BY])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_ISSUE_POSTED_BY, '%row' => $i + 1)); } else { try { entities\User::getB2DBTable()->selectByID($activerow[self::CSV_ISSUE_POSTED_BY]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: user does not exist', array('%col' => self::CSV_ISSUE_POSTED_BY, '%row' => $i + 1)); } } } // Now check milestone exists and is valid if (array_key_exists(self::CSV_ISSUE_MILESTONE, $activerow) && isset($activerow[self::CSV_ISSUE_MILESTONE])) { if (!is_numeric($activerow[self::CSV_ISSUE_MILESTONE])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_ISSUE_MILESTONE, '%row' => $i + 1)); } else { try { $milestonetmp = entities\Milestone::getB2DBTable()->selectById($activerow[self::CSV_ISSUE_MILESTONE]); if ($milestonetmp->getProject()->getID() != $activerow[self::CSV_ISSUE_PROJECT]) { $errors[] = $this->getI18n()->__('Row %row column %col: milestone does not apply to the specified project', array('%col' => self::CSV_ISSUE_MILESTONE, '%row' => $i + 1)); } } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: milestone does not exist', array('%col' => self::CSV_ISSUE_MILESTONE, '%row' => $i + 1)); } } } // status if (array_key_exists(self::CSV_ISSUE_STATUS, $activerow) && isset($activerow[self::CSV_ISSUE_STATUS])) { if (!is_numeric($activerow[self::CSV_ISSUE_STATUS])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_ISSUE_STATUS, '%row' => $i + 1)); } else { try { entities\Status::getB2DBTable()->selectById($activerow[self::CSV_ISSUE_STATUS]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: status does not exist', array('%col' => self::CSV_ISSUE_STATUS, '%row' => $i + 1)); } } } // resolution if (array_key_exists(self::CSV_ISSUE_RESOLUTION, $activerow) && isset($activerow[self::CSV_ISSUE_RESOLUTION])) { if (!is_numeric($activerow[self::CSV_ISSUE_RESOLUTION])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_ISSUE_RESOLUTION, '%row' => $i + 1)); } else { try { entities\Resolution::getB2DBTable()->selectById($activerow[self::CSV_ISSUE_RESOLUTION]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: resolution does not exist', array('%col' => self::CSV_ISSUE_RESOLUTION, '%row' => $i + 1)); } } } // priority if (array_key_exists(self::CSV_ISSUE_PRIORITY, $activerow) && isset($activerow[self::CSV_ISSUE_PRIORITY])) { if (!is_numeric($activerow[self::CSV_ISSUE_PRIORITY])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_ISSUE_PRIORITY, '%row' => $i + 1)); } else { try { entities\Priority::getB2DBTable()->selectById($activerow[self::CSV_ISSUE_PRIORITY]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: priority does not exist', array('%col' => self::CSV_ISSUE_PRIORITY, '%row' => $i + 1)); } } } // category if (array_key_exists(self::CSV_ISSUE_CATEGORY, $activerow) && isset($activerow[self::CSV_ISSUE_CATEGORY])) { if (!is_numeric($activerow[self::CSV_ISSUE_CATEGORY])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_ISSUE_CATEGORY, '%row' => $i + 1)); } else { try { entities\Category::getB2DBTable()->selectById($activerow[self::CSV_ISSUE_CATEGORY]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: category does not exist', array('%col' => self::CSV_ISSUE_CATEGORY, '%row' => $i + 1)); } } } // severity if (array_key_exists(self::CSV_ISSUE_SEVERITY, $activerow) && isset($activerow[self::CSV_ISSUE_SEVERITY])) { if (!is_numeric($activerow[self::CSV_ISSUE_SEVERITY])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_ISSUE_SEVERITY, '%row' => $i + 1)); } else { try { entities\Severity::getB2DBTable()->selectById($activerow[self::CSV_ISSUE_SEVERITY]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: severity does not exist', array('%col' => self::CSV_ISSUE_SEVERITY, '%row' => $i + 1)); } } } // reproducability if (array_key_exists(self::CSV_ISSUE_REPRODUCIBILITY, $activerow) && isset($activerow[self::CSV_ISSUE_REPRODUCIBILITY])) { if (!is_numeric($activerow[self::CSV_ISSUE_REPRODUCIBILITY])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_ISSUE_REPRODUCIBILITY, '%row' => $i + 1)); } else { try { entities\Reproducability::getB2DBTable()->selectById($activerow[self::CSV_ISSUE_REPRODUCIBILITY]); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: reproducability does not exist', array('%col' => self::CSV_ISSUE_REPRODUCIBILITY, '%row' => $i + 1)); } } } // type if (array_key_exists(self::CSV_ISSUE_ISSUE_TYPE, $activerow) && isset($activerow[self::CSV_ISSUE_ISSUE_TYPE])) { if (!is_numeric($activerow[self::CSV_ISSUE_ISSUE_TYPE])) { $errors[] = $this->getI18n()->__('Row %row column %col: invalid value (must be a number)', array('%col' => self::CSV_ISSUE_ISSUE_TYPE, '%row' => $i + 1)); } else { try { $typetmp = entities\Issuetype::getB2DBTable()->selectById($activerow[self::CSV_ISSUE_ISSUE_TYPE]); if (!$prjtmp->getIssuetypeScheme()->isSchemeAssociatedWithIssuetype($typetmp)) { $errors[] = $this->getI18n()->__('Row %row column %col: this project does not support issues of this type (%type)', array('%type' => $typetmp->getName(), '%col' => self::CSV_ISSUE_ISSUE_TYPE, '%row' => $i + 1)); } } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row column %col: issue type does not exist', array('%col' => self::CSV_ISSUE_ISSUE_TYPE, '%row' => $i + 1)); } } } } break; } } // Handle errors if (count($errors) != 0) { $errordiv = '<ul>'; foreach ($errors as $error) { $errordiv .= '<li>' . $error . '</li>'; } $errordiv .= '</ul>'; $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('errordetail' => $errordiv, 'error' => $this->getI18n()->__('Errors occured while importing, see the error list in the import screen for further details'))); } } catch (\Exception $e) { $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('errordetail' => $e->getMessage(), 'error' => $e->getMessage())); } if ($request['csv_dry_run']) { return $this->renderJSON(array('message' => $this->getI18n()->__('Dry-run successful, you can now uncheck the dry-run box and import your data.'))); } else { switch ($request['type']) { case self::CSV_TYPE_CLIENTS: for ($i = 0; $i != count($data); $i++) { try { $activerow = $data[$i]; $client = new entities\Client(); $client->setName($activerow[self::CSV_CLIENT_NAME]); if (isset($activerow[self::CSV_CLIENT_EMAIL])) { $client->setEmail($activerow[self::CSV_CLIENT_EMAIL]); } if (isset($activerow[self::CSV_CLIENT_WEBSITE])) { $client->setWebsite($activerow[self::CSV_CLIENT_WEBSITE]); } if (isset($activerow[self::CSV_CLIENT_FAX])) { $client->setFax($activerow[self::CSV_CLIENT_FAX]); } if (isset($activerow[self::CSV_CLIENT_TELEPHONE])) { $client->setTelephone($activerow[self::CSV_CLIENT_TELEPHONE]); } $client->save(); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row failed: %err', array('%row' => $i + 1, '%err' => $e->getMessage())); } } break; case self::CSV_TYPE_PROJECTS: for ($i = 0; $i != count($data); $i++) { try { $activerow = $data[$i]; $project = new entities\Project(); $project->setName($activerow[self::CSV_PROJECT_NAME]); $project->save(); if (isset($activerow[self::CSV_PROJECT_PREFIX])) { $project->setPrefix($activerow[self::CSV_PROJECT_PREFIX]); $project->setUsePrefix(true); } if (isset($activerow[self::CSV_PROJECT_SCRUM])) { if ($activerow[self::CSV_PROJECT_SCRUM] == '1') { $project->setUsesScrum(true); } } if (isset($activerow[self::CSV_PROJECT_OWNER]) && isset($activerow[self::CSV_PROJECT_OWNER_TYPE])) { switch ($activerow[self::CSV_PROJECT_OWNER_TYPE]) { case self::CSV_IDENTIFIER_TYPE_USER: $user = new entities\User($activerow[self::CSV_PROJECT_OWNER]); $project->setOwner($user); break; case self::CSV_IDENTIFIER_TYPE_TEAM: $team = new entities\Team($activerow[self::CSV_PROJECT_OWNER]); $project->setOwner($team); break; } } if (isset($activerow[self::CSV_PROJECT_LEAD]) && isset($activerow[self::CSV_PROJECT_LEAD_TYPE])) { switch ($activerow[self::CSV_PROJECT_LEAD_TYPE]) { case self::CSV_IDENTIFIER_TYPE_USER: $user = new entities\User($activerow[self::CSV_PROJECT_LEAD]); $project->setLeader($user); break; case self::CSV_IDENTIFIER_TYPE_TEAM: $team = new entities\Team($activerow[self::CSV_PROJECT_LEAD]); $project->setLeader($team); break; } } if (isset($activerow[self::CSV_PROJECT_QA]) && isset($activerow[self::CSV_PROJECT_QA_TYPE])) { switch ($activerow[self::CSV_PROJECT_QA_TYPE]) { case self::CSV_IDENTIFIER_TYPE_USER: $user = new entities\User($activerow[self::CSV_PROJECT_QA]); $project->setQaResponsible($user); break; case self::CSV_IDENTIFIER_TYPE_TEAM: $team = new entities\Team($activerow[self::CSV_PROJECT_QA]); $project->setQaResponsible($team); break; } } if (isset($activerow[self::CSV_PROJECT_DESCR])) { $project->setDescription($activerow[self::CSV_PROJECT_DESCR]); } if (isset($activerow[self::CSV_PROJECT_DOC_URL])) { $project->setDocumentationUrl($activerow[self::CSV_PROJECT_DOC_URL]); } if (isset($activerow[self::CSV_PROJECT_WIKI_URL])) { $project->setWikiUrl($activerow[self::CSV_PROJECT_WIKI_URL]); } if (isset($activerow[self::CSV_PROJECT_FREELANCE])) { if ($activerow[self::CSV_PROJECT_FREELANCE] == '1') { $project->setChangeIssuesWithoutWorkingOnThem(true); } } if (isset($activerow[self::CSV_PROJECT_EN_BUILDS])) { if ($activerow[self::CSV_PROJECT_EN_BUILDS] == '1') { $project->setBuildsEnabled(true); } } if (isset($activerow[self::CSV_PROJECT_EN_COMPS])) { if ($activerow[self::CSV_PROJECT_EN_COMPS] == '1') { $project->setComponentsEnabled(true); } } if (isset($activerow[self::CSV_PROJECT_EN_EDITIONS])) { if ($activerow[self::CSV_PROJECT_EN_EDITIONS] == '1') { $project->setEditionsEnabled(true); } } if (isset($activerow[self::CSV_PROJECT_CLIENT])) { $project->setClient(entities\Client::getB2DBTable()->selectById($activerow[self::CSV_PROJECT_CLIENT])); } if (isset($activerow[self::CSV_PROJECT_SHOW_SUMMARY])) { if ($activerow[self::CSV_PROJECT_SHOW_SUMMARY] == '1') { $project->setFrontpageSummaryVisibility(true); } } if (isset($activerow[self::CSV_PROJECT_SUMMARY_TYPE])) { $project->setFrontpageSummaryType($activerow[self::CSV_PROJECT_SUMMARY_TYPE]); } if (isset($activerow[self::CSV_PROJECT_ALLOW_REPORTING])) { $project->setLocked($activerow[self::CSV_PROJECT_ALLOW_REPORTING]); } if (isset($activerow[self::CSV_PROJECT_AUTOASSIGN])) { $project->setAutoassign($activerow[self::CSV_PROJECT_AUTOASSIGN]); } if (isset($activerow[self::CSV_PROJECT_ISSUETYPE_SCHEME])) { $project->setIssuetypeScheme(entities\IssuetypeScheme::getB2DBTable()->selectById($activerow[self::CSV_PROJECT_ISSUETYPE_SCHEME])); } if (isset($activerow[self::CSV_PROJECT_WORKFLOW_ID])) { } $project->setWorkflowScheme(entities\WorkflowScheme::getB2DBTable()->selectById($activerow[self::CSV_PROJECT_WORKFLOW_ID])); $project->save(); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row failed: %err', array('%row' => $i + 1, '%err' => $e->getMessage())); } } break; case self::CSV_TYPE_ISSUES: for ($i = 0; $i != count($data); $i++) { try { $activerow = $data[$i]; $issue = new entities\Issue(); $issue->setTitle($activerow[self::CSV_ISSUE_TITLE]); $issue->setProject($activerow[self::CSV_ISSUE_PROJECT]); $issue->setIssuetype($activerow[self::CSV_ISSUE_ISSUE_TYPE]); $issue->save(); if (isset($activerow[self::CSV_ISSUE_DESCR])) { $issue->setDescription($activerow[self::CSV_ISSUE_DESCR]); } if (isset($activerow[self::CSV_ISSUE_REPRO])) { $issue->setReproductionSteps($activerow[self::CSV_ISSUE_REPRO]); } if (isset($activerow[self::CSV_ISSUE_STATE])) { $issue->setState($activerow[self::CSV_ISSUE_STATE]); } if (isset($activerow[self::CSV_ISSUE_STATUS])) { $issue->setStatus($activerow[self::CSV_ISSUE_STATUS]); } if (isset($activerow[self::CSV_ISSUE_POSTED_BY])) { $issue->setPostedBy(entities\User::getB2DBTable()->selectByID($activerow[self::CSV_ISSUE_POSTED_BY])); } if (isset($activerow[self::CSV_ISSUE_OWNER]) && isset($activerow[self::CSV_ISSUE_OWNER_TYPE])) { switch ($activerow[self::CSV_ISSUE_OWNER_TYPE]) { case self::CSV_IDENTIFIER_TYPE_USER: $user = new entities\User($activerow[self::CSV_ISSUE_OWNER]); $issue->setOwner($user); break; case self::CSV_IDENTIFIER_TYPE_TEAM: $team = new entities\Team($activerow[self::CSV_ISSUE_OWNER]); $issue->setOwner($team); break; } } if (isset($activerow[self::CSV_ISSUE_ASSIGNED]) && isset($activerow[self::CSV_ISSUE_ASSIGNED_TYPE])) { switch ($activerow[self::CSV_ISSUE_ASSIGNED_TYPE]) { case self::CSV_IDENTIFIER_TYPE_USER: $user = new entities\User($activerow[self::CSV_ISSUE_ASSIGNED]); $issue->setAssignee($user); break; case self::CSV_IDENTIFIER_TYPE_TEAM: $team = new entities\Team($activerow[self::CSV_ISSUE_ASSIGNED]); $issue->setAssignee($team); break; } } if (isset($activerow[self::CSV_ISSUE_RESOLUTION])) { $issue->setResolution($activerow[self::CSV_ISSUE_RESOLUTION]); } if (isset($activerow[self::CSV_ISSUE_PRIORITY])) { $issue->setPriority($activerow[self::CSV_ISSUE_PRIORITY]); } if (isset($activerow[self::CSV_ISSUE_CATEGORY])) { $issue->setCategory($activerow[self::CSV_ISSUE_CATEGORY]); } if (isset($activerow[self::CSV_ISSUE_BLOCKING])) { $issue->setBlocking($activerow[self::CSV_ISSUE_BLOCKING]); } if (isset($activerow[self::CSV_ISSUE_SEVERITY])) { $issue->setSeverity($activerow[self::CSV_ISSUE_SEVERITY]); } if (isset($activerow[self::CSV_ISSUE_REPRODUCIBILITY])) { $issue->setReproducability($activerow[self::CSV_ISSUE_REPRODUCIBILITY]); } if (isset($activerow[self::CSV_ISSUE_VOTES])) { $issue->setVotes($activerow[self::CSV_ISSUE_VOTES]); } if (isset($activerow[self::CSV_ISSUE_PERCENTAGE])) { $issue->setPercentCompleted($activerow[self::CSV_ISSUE_PERCENTAGE]); } if (isset($activerow[self::CSV_ISSUE_ISSUENO])) { $issue->setIssueNo((int) $activerow[self::CSV_ISSUE_ISSUENO]); } if (isset($activerow[self::CSV_ISSUE_MILESTONE])) { $issue->setMilestone($activerow[self::CSV_ISSUE_MILESTONE]); } if (isset($activerow[self::CSV_ISSUE_POSTED])) { $issue->setPosted((int) $activerow[self::CSV_ISSUE_POSTED]); } $issue->save(); } catch (\Exception $e) { $errors[] = $this->getI18n()->__('Row %row failed: %err', array('%row' => $i + 1, '%err' => $e->getMessage())); } } break; } // Handle errors if (count($errors) != 0) { $errordiv = '<ul>'; foreach ($errors as $error) { $errordiv .= '<li>' . $error . '</li>'; } $errordiv .= '</ul>'; $this->getResponse()->setHttpStatus(400); return $this->renderJSON(array('errordetail' => $errordiv, 'error' => $this->getI18n()->__('Errors occured while importing, see the error list in the import screen for further details'))); } else { return $this->renderJSON(array('message' => $this->getI18n()->__('Successfully imported %num rows!', array('%num' => count($data))))); } } }