private function materializeProject(PhabricatorProject $project)
 {
     if ($project->isMilestone()) {
         return;
     }
     $material_type = PhabricatorProjectMaterializedMemberEdgeType::EDGECONST;
     $member_type = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
     $project_phid = $project->getPHID();
     $descendants = id(new PhabricatorProjectQuery())->setViewer($this->getViewer())->withAncestorProjectPHIDs(array($project->getPHID()))->withIsMilestone(false)->withHasSubprojects(false)->execute();
     $descendant_phids = mpull($descendants, 'getPHID');
     if ($descendant_phids) {
         $source_phids = $descendant_phids;
         $has_subprojects = true;
     } else {
         $source_phids = array($project->getPHID());
         $has_subprojects = false;
     }
     $conn_w = $project->establishConnection('w');
     $project->openTransaction();
     // Delete any existing materialized member edges.
     queryfx($conn_w, 'DELETE FROM %T WHERE src = %s AND type = %s', PhabricatorEdgeConfig::TABLE_NAME_EDGE, $project_phid, $material_type);
     // Copy current member edges to create new materialized edges.
     queryfx($conn_w, 'INSERT IGNORE INTO %T (src, type, dst, dateCreated, seq)
       SELECT %s, %d, dst, dateCreated, seq FROM %T
       WHERE src IN (%Ls) AND type = %d', PhabricatorEdgeConfig::TABLE_NAME_EDGE, $project_phid, $material_type, PhabricatorEdgeConfig::TABLE_NAME_EDGE, $source_phids, $member_type);
     // Update the hasSubprojects flag.
     queryfx($conn_w, 'UPDATE %T SET hasSubprojects = %d WHERE id = %d', $project->getTableName(), (int) $has_subprojects, $project->getID());
     $project->saveTransaction();
 }
 public function processRequest()
 {
     $request = $this->getRequest();
     $user = $request->getUser();
     $project = new PhabricatorProject();
     $project->setAuthorPHID($user->getPHID());
     $profile = new PhabricatorProjectProfile();
     $e_name = true;
     $errors = array();
     if ($request->isFormPost()) {
         try {
             $editor = new PhabricatorProjectEditor($project);
             $editor->setUser($user);
             $editor->setName($request->getStr('name'));
             $editor->save();
         } catch (PhabricatorProjectNameCollisionException $ex) {
             $e_name = 'Not Unique';
             $errors[] = $ex->getMessage();
         }
         $project->setStatus(PhabricatorProjectStatus::ONGOING);
         $profile->setBlurb($request->getStr('blurb'));
         if (!$errors) {
             $project->save();
             $profile->setProjectPHID($project->getPHID());
             $profile->save();
             id(new PhabricatorProjectAffiliation())->setUserPHID($user->getPHID())->setProjectPHID($project->getPHID())->setRole('Owner')->setIsOwner(true)->save();
             if ($request->isAjax()) {
                 return id(new AphrontAjaxResponse())->setContent(array('phid' => $project->getPHID(), 'name' => $project->getName()));
             } else {
                 return id(new AphrontRedirectResponse())->setURI('/project/view/' . $project->getID() . '/');
             }
         }
     }
     $error_view = null;
     if ($errors) {
         $error_view = new AphrontErrorView();
         $error_view->setTitle('Form Errors');
         $error_view->setErrors($errors);
     }
     if ($request->isAjax()) {
         $form = new AphrontFormLayoutView();
     } else {
         $form = new AphrontFormView();
         $form->setUser($user);
     }
     $form->appendChild(id(new AphrontFormTextControl())->setLabel('Name')->setName('name')->setValue($project->getName())->setError($e_name))->appendChild(id(new AphrontFormTextAreaControl())->setLabel('Blurb')->setName('blurb')->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)->setValue($profile->getBlurb()));
     if ($request->isAjax()) {
         if ($error_view) {
             $error_view->setWidth(AphrontErrorView::WIDTH_DIALOG);
         }
         $dialog = id(new AphrontDialogView())->setUser($user)->setWidth(AphrontDialogView::WIDTH_FORM)->setTitle('Create a New Project')->appendChild($error_view)->appendChild($form)->addSubmitButton('Create Project')->addCancelButton('/project/');
         return id(new AphrontDialogResponse())->setDialog($dialog);
     } else {
         $form->appendChild(id(new AphrontFormSubmitControl())->setValue('Create')->addCancelButton('/project/'));
         $panel = new AphrontPanelView();
         $panel->setWidth(AphrontPanelView::WIDTH_FORM)->setHeader('Create a New Project')->appendChild($form);
         return $this->buildStandardPageResponse(array($error_view, $panel), array('title' => 'Create new Project'));
     }
 }
 public static function updateProjectSubproject(PhabricatorProject $project)
 {
     $dao = new PhabricatorProjectSubproject();
     $conn = $dao->establishConnection('w');
     $sql = array();
     foreach ($project->getSubprojectPHIDs() as $subproject_phid) {
         $sql[] = qsprintf($conn, '(%s, %s)', $project->getPHID(), $subproject_phid);
     }
     queryfx($conn, 'DELETE FROM %T WHERE projectPHID = %s', $dao->getTableName(), $project->getPHID());
     if ($sql) {
         queryfx($conn, 'INSERT INTO %T (projectPHID, subprojectPHID) VALUES %Q', $dao->getTableName(), implode(', ', $sql));
     }
 }
 protected function buildLocalNavigation(PhabricatorProject $project)
 {
     $id = $project->getID();
     $nav_view = new AphrontSideNavFilterView();
     $uri = new PhutilURI('/project/view/' . $id . '/');
     $nav_view->setBaseURI($uri);
     $external_arrow = "↗";
     $tasks_uri = '/maniphest/view/all/?projects=' . $project->getPHID();
     $slug = PhabricatorSlug::normalize($project->getName());
     $phriction_uri = '/w/projects/' . $slug;
     $edit_uri = '/project/edit/' . $id . '/';
     $members_uri = '/project/members/' . $id . '/';
     $nav_view->addFilter('dashboard', 'Dashboard');
     $nav_view->addSpacer();
     $nav_view->addFilter('feed', 'Feed');
     $nav_view->addFilter(null, 'Tasks ' . $external_arrow, $tasks_uri);
     $nav_view->addFilter(null, 'Wiki ' . $external_arrow, $phriction_uri);
     $nav_view->addFilter('people', 'People');
     $nav_view->addFilter('about', 'About');
     $user = $this->getRequest()->getUser();
     $can_edit = PhabricatorPolicyCapability::CAN_EDIT;
     $nav_view->addSpacer();
     if (PhabricatorPolicyFilter::hasCapability($user, $project, $can_edit)) {
         $nav_view->addFilter('edit', "Edit Project…", $edit_uri);
         $nav_view->addFilter('members', "Edit Members…", $members_uri);
     } else {
         $nav_view->addFilter('edit', "Edit Project…", $edit_uri, $relative = false, 'disabled');
         $nav_view->addFilter('members', "Edit Members…", $members_uri, $relative = false, 'disabled');
     }
     return $nav_view;
 }
 private function buildPropertyListView(PhabricatorProject $project, PhabricatorActionListView $actions)
 {
     $request = $this->getRequest();
     $viewer = $request->getUser();
     $view = id(new PHUIPropertyListView())->setUser($viewer)->setActionList($actions);
     $view->addProperty(pht('Looks Like'), $viewer->renderHandle($project->getPHID())->setAsTag(true));
     return $view;
 }
 private function buildPropertyListView(PhabricatorProject $project)
 {
     $viewer = $this->getViewer();
     $view = id(new PHUIPropertyListView())->setUser($viewer);
     $view->addProperty(pht('Looks Like'), $viewer->renderHandle($project->getPHID())->setAsTag(true));
     $field_list = PhabricatorCustomField::getObjectFields($project, PhabricatorCustomField::ROLE_VIEW);
     $field_list->appendFieldsToPropertyList($project, $viewer, $view);
     return $view;
 }
 private function renderFeedPage(PhabricatorProject $project)
 {
     $query = new PhabricatorFeedQuery();
     $query->setFilterPHIDs(array($project->getPHID()));
     $query->setViewer($this->getRequest()->getUser());
     $query->setLimit(100);
     $stories = $query->execute();
     if (!$stories) {
         return pht('There are no stories about this project.');
     }
     return $this->renderStories($stories);
 }
 private function renderTasksPage(PhabricatorProject $project)
 {
     $user = $this->getRequest()->getUser();
     $query = id(new ManiphestTaskQuery())->setViewer($user)->withAnyProjects(array($project->getPHID()))->withStatuses(ManiphestTaskStatus::getOpenStatusConstants())->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY)->setLimit(10);
     $tasks = $query->execute();
     $phids = mpull($tasks, 'getOwnerPHID');
     $phids = array_merge($phids, array_mergev(mpull($tasks, 'getProjectPHIDs')));
     $phids = array_filter($phids);
     $handles = $this->loadViewerHandles($phids);
     $task_list = new ManiphestTaskListView();
     $task_list->setUser($user);
     $task_list->setTasks($tasks);
     $task_list->setHandles($handles);
     $phid = $project->getPHID();
     $view_uri = urisprintf('/maniphest/?statuses=%s&allProjects=%s#R', implode(',', ManiphestTaskStatus::getOpenStatusConstants()), $phid);
     $create_uri = '/maniphest/task/create/?projects=' . $phid;
     $icon = id(new PHUIIconView())->setIconFont('fa-list');
     $button_view = id(new PHUIButtonView())->setTag('a')->setText(pht('View All'))->setHref($view_uri)->setIcon($icon);
     $icon_new = id(new PHUIIconView())->setIconFont('fa-plus');
     $button_add = id(new PHUIButtonView())->setTag('a')->setText(pht('New Task'))->setHref($create_uri)->setIcon($icon_new);
     $header = id(new PHUIHeaderView())->setHeader(pht('Open Tasks'))->addActionLink($button_add)->addActionLink($button_view);
     $content = id(new PHUIObjectBoxView())->setHeader($header)->appendChild($task_list);
     return $content;
 }
 private function removeSlugs(PhabricatorProject $project, array $slugs)
 {
     $slugs = $this->normalizeSlugs($slugs);
     if (!$slugs) {
         return;
     }
     $objects = id(new PhabricatorProjectSlug())->loadAllWhere('projectPHID = %s AND slug IN (%Ls)', $project->getPHID(), $slugs);
     foreach ($objects as $object) {
         $object->delete();
     }
 }
 private function publishTransactionStory(PhabricatorProject $project, PhabricatorProjectTransaction $xaction)
 {
     $related_phids = array($project->getPHID(), $xaction->getAuthorPHID());
     id(new PhabricatorFeedStoryPublisher())->setStoryType(PhabricatorFeedStoryTypeConstants::STORY_PROJECT)->setStoryData(array('projectPHID' => $project->getPHID(), 'transactionID' => $xaction->getID(), 'type' => $xaction->getTransactionType(), 'old' => $xaction->getOldValue(), 'new' => $xaction->getNewValue()))->setStoryTime(time())->setStoryAuthorPHID($xaction->getAuthorPHID())->setRelatedPHIDs($related_phids)->publish();
 }
 private function renderDefaultForm(PhabricatorProject $project)
 {
     $viewer = $this->getViewer();
     $compose_color = $project->getDisplayIconComposeColor();
     $compose_icon = $project->getDisplayIconComposeIcon();
     $default_builtin = id(new PhabricatorFilesComposeIconBuiltinFile())->setColor($compose_color)->setIcon($compose_icon);
     $file_builtins = PhabricatorFile::loadBuiltins($viewer, array($default_builtin));
     $file_builtin = head($file_builtins);
     $default_button = javelin_tag('button', array('class' => 'grey profile-image-button', 'sigil' => 'has-tooltip', 'meta' => array('tip' => pht('Use Icon and Color'), 'size' => 300)), phutil_tag('img', array('height' => 50, 'width' => 50, 'src' => $file_builtin->getBestURI())));
     $inputs = array('projectPHID' => $project->getPHID(), 'icon' => $compose_icon, 'color' => $compose_color);
     foreach ($inputs as $key => $value) {
         $inputs[$key] = javelin_tag('input', array('type' => 'hidden', 'name' => $key, 'value' => $value));
     }
     $default_form = phabricator_form($viewer, array('class' => 'profile-image-form', 'method' => 'POST', 'action' => '/file/compose/'), array($inputs, $default_button));
     return $default_form;
 }
 public function buildSprintIconNavView(PhabricatorProject $project)
 {
     $viewer = $this->getViewer();
     $id = $project->getID();
     $picture = $project->getProfileImageURI();
     $name = $project->getName();
     $enable_phragile = PhabricatorEnv::getEnvConfig('sprint.enable-phragile');
     $phragile_base_uri = PhabricatorEnv::getEnvConfig('sprint.phragile-uri');
     $phragile_uri = new PhutilURI($phragile_base_uri . $id);
     $columns = id(new PhabricatorProjectColumnQuery())->setViewer($viewer)->withProjectPHIDs(array($project->getPHID()))->execute();
     if ($columns) {
         $board_icon = 'fa-columns';
     } else {
         $board_icon = 'fa-columns grey';
     }
     $nav = new AphrontSideNavFilterView();
     $nav->setIconNav(true);
     if ($this->isSprint($project) !== false) {
         $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
         $nav->addIcon("profile/{$id}/", $name, null, $picture, null);
         $nav->addIcon("burn/{$id}/", pht('Burndown'), 'fa-fire', null, null);
         if ($enable_phragile) {
             $nav->addIcon("sprints/{$id}/", pht('Phragile'), 'fa-pie-chart', null, $phragile_uri);
         }
         $nav->addIcon("board/{$id}/", pht('Sprint Board'), $board_icon, null, null);
         $nav->addIcon('.', pht('Sprint List'), 'fa-bar-chart', null, null);
     } else {
         $nav->setBaseURI(new PhutilURI($this->getProjectsURI()));
         $nav->addIcon("profile/{$id}/", $name, null, $picture);
         $nav->addIcon("board/{$id}/", pht('Workboard'), $board_icon);
     }
     $class = 'PhabricatorManiphestApplication';
     if (PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) {
         $phid = $project->getPHID();
         $query_uri = urisprintf('/maniphest/?statuses=open()&projects=%s#R', $phid);
         $nav->addIcon(null, pht('Open Tasks'), 'fa-anchor', null, $query_uri);
     }
     $nav->addIcon("feed/{$id}/", pht('Feed'), 'fa-newspaper-o', null, null);
     $nav->addIcon("members/{$id}/", pht('Members'), 'fa-group', null, null);
     $nav->addIcon("details/{$id}/", pht('Edit Details'), 'fa-pencil', null, null);
     return $nav;
 }
 private function createProject(PhabricatorUser $user, PhabricatorProject $parent = null, $is_milestone = false)
 {
     $project = PhabricatorProject::initializeNewProject($user);
     $name = pht('Test Project %d', mt_rand());
     $xactions = array();
     $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME)->setNewValue($name);
     if ($parent) {
         if ($is_milestone) {
             $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorProjectTransaction::TYPE_MILESTONE)->setNewValue($parent->getPHID());
         } else {
             $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorProjectTransaction::TYPE_PARENT)->setNewValue($parent->getPHID());
         }
     }
     $this->applyTransactions($project, $user, $xactions);
     return $project;
 }
 private function buildInitializeContent(PhabricatorProject $project)
 {
     $request = $this->getRequest();
     $viewer = $this->getViewer();
     $type = $request->getStr('initialize-type');
     $id = $project->getID();
     $profile_uri = $this->getApplicationURI("profile/{$id}/");
     $board_uri = $this->getApplicationURI("board/{$id}/");
     $import_uri = $this->getApplicationURI("board/{$id}/import/");
     $set_default = $request->getBool('default');
     if ($set_default) {
         $this->getProfilePanelEngine()->adjustDefault(PhabricatorProject::PANEL_WORKBOARD);
     }
     if ($request->isFormPost()) {
         if ($type == 'backlog-only') {
             $column = PhabricatorProjectColumn::initializeNewColumn($viewer)->setSequence(0)->setProperty('isDefault', true)->setProjectPHID($project->getPHID())->save();
             $project->setHasWorkboard(1)->save();
             return id(new AphrontRedirectResponse())->setURI($board_uri);
         } else {
             return id(new AphrontRedirectResponse())->setURI($import_uri);
         }
     }
     $new_selector = id(new AphrontFormRadioButtonControl())->setLabel(pht('Columns'))->setName('initialize-type')->setValue('backlog-only')->addButton('backlog-only', pht('New Empty Board'), pht('Create a new board with just a backlog column.'))->addButton('import', pht('Import Columns'), pht('Import board columns from another project.'));
     $default_checkbox = id(new AphrontFormCheckboxControl())->setLabel(pht('Make Default'))->addCheckbox('default', 1, pht('Make the workboard the default view for this project.'), true);
     $form = id(new AphrontFormView())->setUser($viewer)->appendRemarkupInstructions(pht('The workboard for this project has not been created yet.'))->appendControl($new_selector)->appendControl($default_checkbox)->appendControl(id(new AphrontFormSubmitControl())->addCancelButton($profile_uri)->setValue(pht('Create Workboard')));
     $box = id(new PHUIObjectBoxView())->setHeaderText(pht('Create Workboard'))->setForm($form);
     return $box;
 }
 private function buildSubprojectList(PhabricatorProject $project)
 {
     if (!$project->getHasSubprojects()) {
         return null;
     }
     $viewer = $this->getViewer();
     $id = $project->getID();
     $limit = 25;
     $subprojects = id(new PhabricatorProjectQuery())->setViewer($viewer)->withParentProjectPHIDs(array($project->getPHID()))->needImages(true)->withStatuses(array(PhabricatorProjectStatus::STATUS_ACTIVE))->withIsMilestone(false)->setLimit($limit)->execute();
     if (!$subprojects) {
         return null;
     }
     $subproject_list = id(new PhabricatorProjectListView())->setUser($viewer)->setProjects($subprojects)->renderList();
     $view_all = id(new PHUIButtonView())->setTag('a')->setIcon(id(new PHUIIconView())->setIcon('fa-list-ul'))->setText(pht('View All'))->setHref("/project/subprojects/{$id}/");
     $header = id(new PHUIHeaderView())->setHeader(pht('Subprojects'))->addActionLink($view_all);
     return id(new PHUIObjectBoxView())->setHeader($header)->setBackground(PHUIBoxView::GREY)->setObjectList($subproject_list);
 }
Пример #16
0
 protected function buildProjectInfoDictionary(PhabricatorProject $project)
 {
     $results = $this->buildProjectInfoDictionaries(array($project));
     return idx($results, $project->getPHID());
 }
 private function renderTasksPage(PhabricatorProject $project, PhabricatorProjectProfile $profile)
 {
     $query = id(new ManiphestTaskQuery())->withProjects(array($project->getPHID()))->withStatus(ManiphestTaskQuery::STATUS_OPEN)->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY)->setLimit(10)->setCalculateRows(true);
     $tasks = $query->execute();
     $count = $query->getRowCount();
     $phids = mpull($tasks, 'getOwnerPHID');
     $phids = array_filter($phids);
     $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
     $task_views = array();
     foreach ($tasks as $task) {
         $view = id(new ManiphestTaskSummaryView())->setTask($task)->setHandles($handles)->setUser($this->getRequest()->getUser());
         $task_views[] = $view->render();
     }
     if (empty($tasks)) {
         $task_views = '<em>No open tasks.</em>';
     } else {
         $task_views = implode('', $task_views);
     }
     $open = number_format($count);
     $more_link = phutil_render_tag('a', array('href' => '/maniphest/view/all/?projects=' . $project->getPHID()), "View All Open Tasks »");
     $content = '<div class="phabricator-profile-info-group">
     <h1 class="phabricator-profile-info-header">' . "Open Tasks ({$open})" . '</h1>' . '<div class="phabricator-profile-info-pane">' . $task_views . '<div class="phabricator-profile-info-pane-more-link">' . $more_link . '</div>' . '</div>
   </div>';
     return $content;
 }
 private function isProjectSilenced(PhabricatorProject $project)
 {
     $viewer = $this->getViewer();
     $viewer_phid = $viewer->getPHID();
     if (!$viewer_phid) {
         return false;
     }
     $edge_type = PhabricatorProjectSilencedEdgeType::EDGECONST;
     $silenced = PhabricatorEdgeQuery::loadDestinationPHIDs($project->getPHID(), $edge_type);
     $silenced = array_fuse($silenced);
     return isset($silenced[$viewer_phid]);
 }
 private function removeSlugs(PhabricatorProject $project, array $slugs)
 {
     if (!$slugs) {
         return;
     }
     // We're going to try to delete both the literal and normalized versions
     // of all slugs. This allows us to destroy old slugs that are no longer
     // valid.
     foreach ($this->normalizeSlugs($slugs) as $slug) {
         $slugs[] = $slug;
     }
     $objects = id(new PhabricatorProjectSlug())->loadAllWhere('projectPHID = %s AND slug IN (%Ls)', $project->getPHID(), $slugs);
     foreach ($objects as $object) {
         $object->delete();
     }
 }
 private function createProject(PhabricatorUser $user, PhabricatorProject $parent = null, $is_milestone = false)
 {
     $project = PhabricatorProject::initializeNewProject($user);
     $name = pht('Test Project %d', mt_rand());
     $xactions = array();
     $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME)->setNewValue($name);
     if ($parent) {
         if ($is_milestone) {
             $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorProjectTransaction::TYPE_MILESTONE)->setNewValue($parent->getPHID());
         } else {
             $xactions[] = id(new PhabricatorProjectTransaction())->setTransactionType(PhabricatorProjectTransaction::TYPE_PARENT)->setNewValue($parent->getPHID());
         }
     }
     $this->applyTransactions($project, $user, $xactions);
     // Force these values immediately; they are normally updated by the
     // index engine.
     if ($parent) {
         if ($is_milestone) {
             $parent->setHasMilestones(1)->save();
         } else {
             $parent->setHasSubprojects(1)->save();
         }
     }
     return $project;
 }