mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-03 11:21:01 +01:00
Some owners write workflows.
This commit is contained in:
parent
5038ab850c
commit
23f882a0ee
24 changed files with 730 additions and 174 deletions
|
@ -1,6 +1,6 @@
|
||||||
CREATE DATABASE phabricator_owners;
|
CREATE DATABASE phabricator_owners;
|
||||||
|
|
||||||
CREATE TABLE phabricator_owners.onwners_package (
|
CREATE TABLE phabricator_owners.owners_package (
|
||||||
id int unsigned not null auto_increment primary key,
|
id int unsigned not null auto_increment primary key,
|
||||||
phid varchar(64) binary not null,
|
phid varchar(64) binary not null,
|
||||||
unique key(phid),
|
unique key(phid),
|
||||||
|
@ -23,6 +23,5 @@ CREATE TABLE phabricator_owners.owners_path (
|
||||||
packageID int unsigned not null,
|
packageID int unsigned not null,
|
||||||
key(packageID),
|
key(packageID),
|
||||||
repositoryPHID varchar(64) binary not null,
|
repositoryPHID varchar(64) binary not null,
|
||||||
path varchar(255) not null,
|
path varchar(255) not null
|
||||||
unique key (repositoryPHID, path)
|
|
||||||
);
|
);
|
|
@ -63,7 +63,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'aphront-list-filter-view-css' =>
|
'aphront-list-filter-view-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/89f641c5/rsrc/css/aphront/list-filter-view.css',
|
'uri' => '/res/50a790ae/rsrc/css/aphront/list-filter-view.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -81,7 +81,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'aphront-panel-view-css' =>
|
'aphront-panel-view-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/63672373/rsrc/css/aphront/panel-view.css',
|
'uri' => '/res/8f9f3632/rsrc/css/aphront/panel-view.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -643,7 +643,7 @@ celerity_register_resource_map(array(
|
||||||
), array (
|
), array (
|
||||||
'packages' =>
|
'packages' =>
|
||||||
array (
|
array (
|
||||||
'e3ec35d7' =>
|
'2de9aa4e' =>
|
||||||
array (
|
array (
|
||||||
'name' => 'core.pkg.css',
|
'name' => 'core.pkg.css',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
|
@ -663,7 +663,7 @@ celerity_register_resource_map(array(
|
||||||
12 => 'phabricator-remarkup-css',
|
12 => 'phabricator-remarkup-css',
|
||||||
13 => 'syntax-highlighting-css',
|
13 => 'syntax-highlighting-css',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/e3ec35d7/core.pkg.css',
|
'uri' => '/res/pkg/2de9aa4e/core.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
'76f3c1f8' =>
|
'76f3c1f8' =>
|
||||||
|
@ -710,20 +710,20 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'reverse' =>
|
'reverse' =>
|
||||||
array (
|
array (
|
||||||
'phabricator-core-css' => 'e3ec35d7',
|
'phabricator-core-css' => '2de9aa4e',
|
||||||
'phabricator-core-buttons-css' => 'e3ec35d7',
|
'phabricator-core-buttons-css' => '2de9aa4e',
|
||||||
'phabricator-standard-page-view' => 'e3ec35d7',
|
'phabricator-standard-page-view' => '2de9aa4e',
|
||||||
'aphront-dialog-view-css' => 'e3ec35d7',
|
'aphront-dialog-view-css' => '2de9aa4e',
|
||||||
'aphront-form-view-css' => 'e3ec35d7',
|
'aphront-form-view-css' => '2de9aa4e',
|
||||||
'aphront-panel-view-css' => 'e3ec35d7',
|
'aphront-panel-view-css' => '2de9aa4e',
|
||||||
'aphront-side-nav-view-css' => 'e3ec35d7',
|
'aphront-side-nav-view-css' => '2de9aa4e',
|
||||||
'aphront-table-view-css' => 'e3ec35d7',
|
'aphront-table-view-css' => '2de9aa4e',
|
||||||
'aphront-crumbs-view-css' => 'e3ec35d7',
|
'aphront-crumbs-view-css' => '2de9aa4e',
|
||||||
'aphront-tokenizer-control-css' => 'e3ec35d7',
|
'aphront-tokenizer-control-css' => '2de9aa4e',
|
||||||
'aphront-typeahead-control-css' => 'e3ec35d7',
|
'aphront-typeahead-control-css' => '2de9aa4e',
|
||||||
'phabricator-directory-css' => 'e3ec35d7',
|
'phabricator-directory-css' => '2de9aa4e',
|
||||||
'phabricator-remarkup-css' => 'e3ec35d7',
|
'phabricator-remarkup-css' => '2de9aa4e',
|
||||||
'syntax-highlighting-css' => 'e3ec35d7',
|
'syntax-highlighting-css' => '2de9aa4e',
|
||||||
'differential-core-view-css' => '76f3c1f8',
|
'differential-core-view-css' => '76f3c1f8',
|
||||||
'differential-changeset-view-css' => '76f3c1f8',
|
'differential-changeset-view-css' => '76f3c1f8',
|
||||||
'differential-revision-detail-css' => '76f3c1f8',
|
'differential-revision-detail-css' => '76f3c1f8',
|
||||||
|
|
|
@ -320,7 +320,9 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorObjectSelectorDialog' => 'view/control/objectselector',
|
'PhabricatorObjectSelectorDialog' => 'view/control/objectselector',
|
||||||
'PhabricatorOwnersController' => 'applications/owners/controller/base',
|
'PhabricatorOwnersController' => 'applications/owners/controller/base',
|
||||||
'PhabricatorOwnersDAO' => 'applications/owners/storage/base',
|
'PhabricatorOwnersDAO' => 'applications/owners/storage/base',
|
||||||
|
'PhabricatorOwnersDeleteController' => 'applications/owners/controller/delete',
|
||||||
'PhabricatorOwnersDetailController' => 'applications/owners/controller/detail',
|
'PhabricatorOwnersDetailController' => 'applications/owners/controller/detail',
|
||||||
|
'PhabricatorOwnersEditController' => 'applications/owners/controller/edit',
|
||||||
'PhabricatorOwnersListController' => 'applications/owners/controller/list',
|
'PhabricatorOwnersListController' => 'applications/owners/controller/list',
|
||||||
'PhabricatorOwnersOwner' => 'applications/owners/storage/owner',
|
'PhabricatorOwnersOwner' => 'applications/owners/storage/owner',
|
||||||
'PhabricatorOwnersPackage' => 'applications/owners/storage/package',
|
'PhabricatorOwnersPackage' => 'applications/owners/storage/package',
|
||||||
|
@ -677,7 +679,9 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController',
|
'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController',
|
||||||
'PhabricatorOwnersController' => 'PhabricatorController',
|
'PhabricatorOwnersController' => 'PhabricatorController',
|
||||||
'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO',
|
||||||
|
'PhabricatorOwnersDeleteController' => 'PhabricatorOwnersController',
|
||||||
'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController',
|
'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController',
|
||||||
|
'PhabricatorOwnersEditController' => 'PhabricatorOwnersController',
|
||||||
'PhabricatorOwnersListController' => 'PhabricatorOwnersController',
|
'PhabricatorOwnersListController' => 'PhabricatorOwnersController',
|
||||||
'PhabricatorOwnersOwner' => 'PhabricatorOwnersDAO',
|
'PhabricatorOwnersOwner' => 'PhabricatorOwnersDAO',
|
||||||
'PhabricatorOwnersPackage' => 'PhabricatorOwnersDAO',
|
'PhabricatorOwnersPackage' => 'PhabricatorOwnersDAO',
|
||||||
|
|
|
@ -260,8 +260,10 @@ class AphrontDefaultApplicationConfiguration
|
||||||
'/owners/' => array(
|
'/owners/' => array(
|
||||||
'$' => 'PhabricatorOwnersListController',
|
'$' => 'PhabricatorOwnersListController',
|
||||||
'view/(?P<view>[^/]+)/$' => 'PhabricatorOwnersListController',
|
'view/(?P<view>[^/]+)/$' => 'PhabricatorOwnersListController',
|
||||||
|
'edit/(?P<id>\d+)/$' => 'PhabricatorOwnersEditController',
|
||||||
|
'new/$' => 'PhabricatorOwnersEditController',
|
||||||
'package/(?P<id>\d+)/$' => 'PhabricatorOwnersDetailController',
|
'package/(?P<id>\d+)/$' => 'PhabricatorOwnersDetailController',
|
||||||
'new/$' => 'PhabricatorOwnersDetailController',
|
'delete/(?P<id>\d+)/$' => 'PhabricatorOwnersDeleteController',
|
||||||
),
|
),
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -47,8 +47,7 @@ class DiffusionPathCompleteController extends DiffusionController {
|
||||||
$drequest = DiffusionRequest::newFromAphrontRequestDictionary(
|
$drequest = DiffusionRequest::newFromAphrontRequestDictionary(
|
||||||
array(
|
array(
|
||||||
'callsign' => $repository->getCallsign(),
|
'callsign' => $repository->getCallsign(),
|
||||||
'path' => $query_dir,
|
'path' => ':/'.$query_dir,
|
||||||
'nobranch' => true,
|
|
||||||
));
|
));
|
||||||
|
|
||||||
$browse_query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest);
|
$browse_query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest);
|
||||||
|
|
|
@ -39,8 +39,7 @@ class DiffusionPathValidateController extends DiffusionController {
|
||||||
$drequest = DiffusionRequest::newFromAphrontRequestDictionary(
|
$drequest = DiffusionRequest::newFromAphrontRequestDictionary(
|
||||||
array(
|
array(
|
||||||
'callsign' => $repository->getCallsign(),
|
'callsign' => $repository->getCallsign(),
|
||||||
'path' => $path,
|
'path' => ':/'.$path,
|
||||||
'nobranch' => true,
|
|
||||||
));
|
));
|
||||||
|
|
||||||
$browse_query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest);
|
$browse_query = DiffusionBrowseQuery::newFromDiffusionRequest($drequest);
|
||||||
|
|
|
@ -24,8 +24,8 @@ class DiffusionGitRequest extends DiffusionRequest {
|
||||||
$path = $this->path;
|
$path = $this->path;
|
||||||
$parts = explode('/', $path);
|
$parts = explode('/', $path);
|
||||||
|
|
||||||
if (empty($data['nobranch'])) {
|
$branch = array_shift($parts);
|
||||||
$branch = array_shift($parts);
|
if ($branch != ':') {
|
||||||
$this->branch = $this->decodeBranchName($branch);
|
$this->branch = $this->decodeBranchName($branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,14 @@ class DiffusionSvnRequest extends DiffusionRequest {
|
||||||
|
|
||||||
private $loadedCommit;
|
private $loadedCommit;
|
||||||
|
|
||||||
|
protected function initializeFromAphrontRequestDictionary(array $data) {
|
||||||
|
parent::initializeFromAphrontRequestDictionary($data);
|
||||||
|
if (!strncmp($this->path, ':', 1)) {
|
||||||
|
$this->path = substr($this->path, 1);
|
||||||
|
$this->path = ltrim($this->path, '/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getCommit() {
|
public function getCommit() {
|
||||||
if ($this->commit) {
|
if ($this->commit) {
|
||||||
return $this->commit;
|
return $this->commit;
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PhabricatorOwnersDeleteController extends PhabricatorOwnersController {
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->id = $data['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
$package = id(new PhabricatorOwnersPackage())->load($this->id);
|
||||||
|
if (!$package) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->isDialogFormPost()) {
|
||||||
|
$package->delete();
|
||||||
|
return id(new AphrontRedirectResponse())->setURI('/owners/');
|
||||||
|
}
|
||||||
|
|
||||||
|
$dialog = id(new AphrontDialogView())
|
||||||
|
->setUser($user)
|
||||||
|
->setTitle('Really delete this package?')
|
||||||
|
->appendChild(
|
||||||
|
'<p>Are you sure you want to delete the "'.
|
||||||
|
phutil_escape_html($package->getName()).'" package? This operation '.
|
||||||
|
'can not be undone.</p>')
|
||||||
|
->addSubmitButton('Delete')
|
||||||
|
->addCancelButton('/owners/package/'.$package->getID().'/')
|
||||||
|
->setSubmitURI($request->getRequestURI());
|
||||||
|
|
||||||
|
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
19
src/applications/owners/controller/delete/__init__.php
Normal file
19
src/applications/owners/controller/delete/__init__.php
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/404');
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/dialog');
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/storage/package');
|
||||||
|
phutil_require_module('phabricator', 'view/dialog');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorOwnersDeleteController.php');
|
|
@ -21,132 +21,122 @@ class PhabricatorOwnersDetailController extends PhabricatorOwnersController {
|
||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
public function willProcessRequest(array $data) {
|
||||||
$this->id = idx($data, 'id');
|
$this->id = $data['id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$user = $request->getUser();
|
$user = $request->getUser();
|
||||||
|
|
||||||
if ($this->id) {
|
$package = id(new PhabricatorOwnersPackage())->load($this->id);
|
||||||
$package = id(new PhabricatorOwnersPackage())->load($this->id);
|
if (!$package) {
|
||||||
if (!$package) {
|
return new Aphront404Response();
|
||||||
return new Aphront404Response();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$package = new PhabricatorOwnersPackage();
|
|
||||||
$package->setPrimaryOwnerPHID($user->getPHID());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$e_name = true;
|
$paths = $package->loadPaths();
|
||||||
$e_primary = true;
|
$owners = $package->loadOwners();
|
||||||
|
|
||||||
|
$phids = array();
|
||||||
$token_primary_owner = array();
|
foreach ($paths as $path) {
|
||||||
$token_all_owners = array();
|
$phids[$path->getRepositoryPHID()] = true;
|
||||||
|
|
||||||
$title = $package->getID() ? 'Edit Package' : 'New Package';
|
|
||||||
|
|
||||||
$repos = id(new PhabricatorRepository())->loadAll();
|
|
||||||
|
|
||||||
$default_paths = array();
|
|
||||||
foreach ($repos as $repo) {
|
|
||||||
$default_path = $repo->getDetail('default-owners-path');
|
|
||||||
if ($default_path) {
|
|
||||||
$default_paths[$repo->getPHID()] = $default_path;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
foreach ($owners as $owner) {
|
||||||
|
$phids[$owner->getUserPHID()] = true;
|
||||||
|
}
|
||||||
|
$phids = array_keys($phids);
|
||||||
|
|
||||||
$repos = mpull($repos, 'getCallsign', 'getPHID');
|
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||||
|
|
||||||
$template = new AphrontTypeaheadTemplateView();
|
$rows = array();
|
||||||
$template = $template->render();
|
|
||||||
|
|
||||||
|
$rows[] = array(
|
||||||
|
'Name',
|
||||||
|
phutil_escape_html($package->getName()));
|
||||||
|
$rows[] = array(
|
||||||
|
'Description',
|
||||||
|
phutil_escape_html($package->getDescription()));
|
||||||
|
|
||||||
Javelin::initBehavior(
|
$primary_owner = null;
|
||||||
'owners-path-editor',
|
$primary_phid = $package->getPrimaryOwnerPHID();
|
||||||
|
if ($primary_phid && isset($handles[$primary_phid])) {
|
||||||
|
$primary_owner =
|
||||||
|
'<strong>'.$handles[$primary_phid]->renderLink().'</strong>';
|
||||||
|
}
|
||||||
|
$rows[] = array(
|
||||||
|
'Primary Owner',
|
||||||
|
$primary_owner,
|
||||||
|
);
|
||||||
|
|
||||||
|
$owner_links = array();
|
||||||
|
foreach ($owners as $owner) {
|
||||||
|
$owner_links[] = $handles[$owner->getUserPHID()]->renderLink();
|
||||||
|
}
|
||||||
|
$owner_links = implode('<br />', $owner_links);
|
||||||
|
$rows[] = array(
|
||||||
|
'Owners',
|
||||||
|
$owner_links);
|
||||||
|
|
||||||
|
$path_links = array();
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
$callsign = $handles[$path->getRepositoryPHID()]->getName();
|
||||||
|
$repo = phutil_escape_html('r'.$callsign);
|
||||||
|
$path_link = phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/diffusion/'.$callsign.'/browse/:'.$path->getPath(),
|
||||||
|
),
|
||||||
|
phutil_escape_html($path->getPath()));
|
||||||
|
$path_links[] = $repo.' '.$path_link;
|
||||||
|
}
|
||||||
|
$path_links = implode('<br />', $path_links);
|
||||||
|
$rows[] = array(
|
||||||
|
'Paths',
|
||||||
|
$path_links);
|
||||||
|
|
||||||
|
$table = new AphrontTableView($rows);
|
||||||
|
$table->setColumnClasses(
|
||||||
array(
|
array(
|
||||||
'root' => 'path-editor',
|
'header',
|
||||||
'table' => 'paths',
|
'wide',
|
||||||
'add_button' => 'addpath',
|
|
||||||
'repositories' => $repos,
|
|
||||||
'input_template' => $template,
|
|
||||||
'path_refs' => array(),
|
|
||||||
|
|
||||||
'completeURI' => '/diffusion/services/path/complete/',
|
|
||||||
'validateURI' => '/diffusion/services/path/validate/',
|
|
||||||
|
|
||||||
'repositoryDefaultPaths' => $default_paths,
|
|
||||||
));
|
));
|
||||||
|
|
||||||
require_celerity_resource('owners-path-editor-css');
|
|
||||||
|
|
||||||
$form = id(new AphrontFormView())
|
|
||||||
->setUser($user)
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormTextControl())
|
|
||||||
->setLabel('Name')
|
|
||||||
->setName('name')
|
|
||||||
->setValue($package->getName())
|
|
||||||
->setError($e_name))
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormTokenizerControl())
|
|
||||||
->setDatasource('/typeahead/common/users/')
|
|
||||||
->setLabel('Primary Owner')
|
|
||||||
->setName('primary')
|
|
||||||
->setLimit(1)
|
|
||||||
->setValue($token_primary_owner)
|
|
||||||
->setError($e_primary))
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormTokenizerControl())
|
|
||||||
->setDatasource('/typeahead/common/users/')
|
|
||||||
->setLabel('Owners')
|
|
||||||
->setName('owners')
|
|
||||||
->setValue($token_all_owners)
|
|
||||||
->setError($e_primary))
|
|
||||||
->appendChild(
|
|
||||||
'<h1>Paths</h1>'.
|
|
||||||
'<div class="aphront-form-inset" id="path-editor">'.
|
|
||||||
'<div style="float: right;">'.
|
|
||||||
javelin_render_tag(
|
|
||||||
'a',
|
|
||||||
array(
|
|
||||||
'href' => '#',
|
|
||||||
'class' => 'button green',
|
|
||||||
'sigil' => 'addpath',
|
|
||||||
'mustcapture' => true,
|
|
||||||
),
|
|
||||||
'Add New Path').
|
|
||||||
'</div>'.
|
|
||||||
'<p>Specify the files and directories which comprise this '.
|
|
||||||
'package.</p>'.
|
|
||||||
'<div style="clear: both;"></div>'.
|
|
||||||
javelin_render_tag(
|
|
||||||
'table',
|
|
||||||
array(
|
|
||||||
'class' => 'owners-path-editor-table',
|
|
||||||
'sigil' => 'paths',
|
|
||||||
),
|
|
||||||
'').
|
|
||||||
'</div>')
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormTextAreaControl())
|
|
||||||
->setLabel('Description')
|
|
||||||
->setName('description')
|
|
||||||
->setValue($package->getDescription()))
|
|
||||||
->appendChild(
|
|
||||||
id(new AphrontFormSubmitControl())
|
|
||||||
->setValue('Save Package'));
|
|
||||||
|
|
||||||
$panel = new AphrontPanelView();
|
$panel = new AphrontPanelView();
|
||||||
$panel->setHeader($title);
|
$panel->setHeader(
|
||||||
$panel->setWidth(AphrontPanelView::WIDTH_WIDE);
|
'Package Details for "'.phutil_escape_html($package->getName()).'"');
|
||||||
$panel->appendChild($form);
|
$panel->addButton(
|
||||||
|
javelin_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/owners/delete/'.$package->getID().'/',
|
||||||
|
'class' => 'button grey',
|
||||||
|
'sigil' => 'workflow',
|
||||||
|
),
|
||||||
|
'Delete Package'));
|
||||||
|
$panel->addButton(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/owners/edit/'.$package->getID().'/',
|
||||||
|
'class' => 'button',
|
||||||
|
),
|
||||||
|
'Edit Package'));
|
||||||
|
$panel->appendChild($table);
|
||||||
|
|
||||||
|
$nav = new AphrontSideNavView();
|
||||||
|
$nav->appendChild($panel);
|
||||||
|
$nav->addNavItem(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/owners/package/'.$package->getID().'/',
|
||||||
|
'class' => 'aphront-side-nav-selected',
|
||||||
|
),
|
||||||
|
'Package Details'));
|
||||||
|
|
||||||
return $this->buildStandardPageResponse(
|
return $this->buildStandardPageResponse(
|
||||||
$panel,
|
$nav,
|
||||||
array(
|
array(
|
||||||
'title' => $title,
|
'title' => "Package '".$package->getName()."'",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,14 +9,13 @@
|
||||||
phutil_require_module('phabricator', 'aphront/response/404');
|
phutil_require_module('phabricator', 'aphront/response/404');
|
||||||
phutil_require_module('phabricator', 'applications/owners/controller/base');
|
phutil_require_module('phabricator', 'applications/owners/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/owners/storage/package');
|
phutil_require_module('phabricator', 'applications/owners/storage/package');
|
||||||
phutil_require_module('phabricator', 'applications/repository/storage/repository');
|
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
||||||
phutil_require_module('phabricator', 'infrastructure/javelin/api');
|
phutil_require_module('phabricator', 'view/control/table');
|
||||||
phutil_require_module('phabricator', 'view/control/typeahead');
|
|
||||||
phutil_require_module('phabricator', 'view/form/base');
|
|
||||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
|
||||||
phutil_require_module('phabricator', 'view/layout/panel');
|
phutil_require_module('phabricator', 'view/layout/panel');
|
||||||
|
phutil_require_module('phabricator', 'view/layout/sidenav');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'markup');
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,258 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PhabricatorOwnersEditController extends PhabricatorOwnersController {
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->id = idx($data, 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
if ($this->id) {
|
||||||
|
$package = id(new PhabricatorOwnersPackage())->load($this->id);
|
||||||
|
if (!$package) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$package = new PhabricatorOwnersPackage();
|
||||||
|
$package->setPrimaryOwnerPHID($user->getPHID());
|
||||||
|
}
|
||||||
|
|
||||||
|
$e_name = true;
|
||||||
|
$e_primary = true;
|
||||||
|
$e_owners = true;
|
||||||
|
|
||||||
|
$errors = array();
|
||||||
|
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
$package->setName($request->getStr('name'));
|
||||||
|
$package->setDescription($request->getStr('description'));
|
||||||
|
|
||||||
|
$primary = $request->getArr('primary');
|
||||||
|
$primary = reset($primary);
|
||||||
|
$package->setPrimaryOwnerPHID($primary);
|
||||||
|
|
||||||
|
$owners = $request->getArr('owners');
|
||||||
|
if ($primary) {
|
||||||
|
array_unshift($owners, $primary);
|
||||||
|
}
|
||||||
|
$owners = array_unique($owners);
|
||||||
|
|
||||||
|
$paths = $request->getArr('path');
|
||||||
|
$repos = $request->getArr('repo');
|
||||||
|
|
||||||
|
$path_refs = array();
|
||||||
|
for ($ii = 0; $ii < count($paths); $ii++) {
|
||||||
|
if (empty($paths[$ii]) || empty($repos[$ii])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$path_refs[] = array(
|
||||||
|
'repositoryPHID' => $repos[$ii],
|
||||||
|
'path' => $paths[$ii],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strlen($package->getName())) {
|
||||||
|
$e_name = 'Required';
|
||||||
|
$errors[] = 'Package name is required.';
|
||||||
|
} else {
|
||||||
|
$e_name = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$package->getPrimaryOwnerPHID()) {
|
||||||
|
$e_primary = 'Required';
|
||||||
|
$errors[] = 'Package must have a primary owner.';
|
||||||
|
} else {
|
||||||
|
$e_primary = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$owners) {
|
||||||
|
$e_owners = 'Required';
|
||||||
|
$errors[] = 'Package must have at least one owner.';
|
||||||
|
} else {
|
||||||
|
$e_owners = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$path_refs) {
|
||||||
|
$errors[] = 'Package must include at least one path.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$errors) {
|
||||||
|
$package->attachUnsavedOwners($owners);
|
||||||
|
$package->attachUnsavedPaths($path_refs);
|
||||||
|
try {
|
||||||
|
$package->save();
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI('/owners/package/'.$package->getID().'/');
|
||||||
|
} catch (AphrontQueryDuplicateKeyException $ex) {
|
||||||
|
$e_name = 'Duplicate';
|
||||||
|
$errors[] = 'Package name must be unique.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$owners = $package->loadOwners();
|
||||||
|
$owners = mpull($owners, 'getUserPHID');
|
||||||
|
|
||||||
|
$paths = $package->loadPaths();
|
||||||
|
$path_refs = array();
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
$path_refs[] = array(
|
||||||
|
'repositoryPHID' => $path->getRepositoryPHID(),
|
||||||
|
'path' => $path->getPath(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$error_view = null;
|
||||||
|
if ($errors) {
|
||||||
|
$error_view = new AphrontErrorView();
|
||||||
|
$error_view->setTitle('Package Errors');
|
||||||
|
$error_view->setErrors($errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
$handles = id(new PhabricatorObjectHandleData($owners))
|
||||||
|
->loadHandles();
|
||||||
|
|
||||||
|
$primary = $package->getPrimaryOwnerPHID();
|
||||||
|
if ($primary && isset($handles[$primary])) {
|
||||||
|
$token_primary_owner = array(
|
||||||
|
$primary => $handles[$primary]->getFullName(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$token_primary_owner = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$token_all_owners = array_select_keys($handles, $owners);
|
||||||
|
$token_all_owners = mpull($token_all_owners, 'getFullName');
|
||||||
|
|
||||||
|
$title = $package->getID() ? 'Edit Package' : 'New Package';
|
||||||
|
|
||||||
|
$repos = id(new PhabricatorRepository())->loadAll();
|
||||||
|
|
||||||
|
$default_paths = array();
|
||||||
|
foreach ($repos as $repo) {
|
||||||
|
$default_path = $repo->getDetail('default-owners-path');
|
||||||
|
if ($default_path) {
|
||||||
|
$default_paths[$repo->getPHID()] = $default_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$repos = mpull($repos, 'getCallsign', 'getPHID');
|
||||||
|
|
||||||
|
$template = new AphrontTypeaheadTemplateView();
|
||||||
|
$template = $template->render();
|
||||||
|
|
||||||
|
Javelin::initBehavior(
|
||||||
|
'owners-path-editor',
|
||||||
|
array(
|
||||||
|
'root' => 'path-editor',
|
||||||
|
'table' => 'paths',
|
||||||
|
'add_button' => 'addpath',
|
||||||
|
'repositories' => $repos,
|
||||||
|
'input_template' => $template,
|
||||||
|
'pathRefs' => $path_refs,
|
||||||
|
|
||||||
|
'completeURI' => '/diffusion/services/path/complete/',
|
||||||
|
'validateURI' => '/diffusion/services/path/validate/',
|
||||||
|
|
||||||
|
'repositoryDefaultPaths' => $default_paths,
|
||||||
|
));
|
||||||
|
|
||||||
|
require_celerity_resource('owners-path-editor-css');
|
||||||
|
|
||||||
|
$cancel_uri = $package->getID()
|
||||||
|
? '/owners/package/'.$package->getID().'/'
|
||||||
|
: '/owners/';
|
||||||
|
|
||||||
|
$form = id(new AphrontFormView())
|
||||||
|
->setUser($user)
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTextControl())
|
||||||
|
->setLabel('Name')
|
||||||
|
->setName('name')
|
||||||
|
->setValue($package->getName())
|
||||||
|
->setError($e_name))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTokenizerControl())
|
||||||
|
->setDatasource('/typeahead/common/users/')
|
||||||
|
->setLabel('Primary Owner')
|
||||||
|
->setName('primary')
|
||||||
|
->setLimit(1)
|
||||||
|
->setValue($token_primary_owner)
|
||||||
|
->setError($e_primary))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTokenizerControl())
|
||||||
|
->setDatasource('/typeahead/common/users/')
|
||||||
|
->setLabel('Owners')
|
||||||
|
->setName('owners')
|
||||||
|
->setValue($token_all_owners)
|
||||||
|
->setError($e_owners))
|
||||||
|
->appendChild(
|
||||||
|
'<h1>Paths</h1>'.
|
||||||
|
'<div class="aphront-form-inset" id="path-editor">'.
|
||||||
|
'<div style="float: right;">'.
|
||||||
|
javelin_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '#',
|
||||||
|
'class' => 'button green',
|
||||||
|
'sigil' => 'addpath',
|
||||||
|
'mustcapture' => true,
|
||||||
|
),
|
||||||
|
'Add New Path').
|
||||||
|
'</div>'.
|
||||||
|
'<p>Specify the files and directories which comprise this '.
|
||||||
|
'package.</p>'.
|
||||||
|
'<div style="clear: both;"></div>'.
|
||||||
|
javelin_render_tag(
|
||||||
|
'table',
|
||||||
|
array(
|
||||||
|
'class' => 'owners-path-editor-table',
|
||||||
|
'sigil' => 'paths',
|
||||||
|
),
|
||||||
|
'').
|
||||||
|
'</div>')
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTextAreaControl())
|
||||||
|
->setLabel('Description')
|
||||||
|
->setName('description')
|
||||||
|
->setValue($package->getDescription()))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormSubmitControl())
|
||||||
|
->addCancelButton($cancel_uri)
|
||||||
|
->setValue('Save Package'));
|
||||||
|
|
||||||
|
$panel = new AphrontPanelView();
|
||||||
|
$panel->setHeader($title);
|
||||||
|
$panel->setWidth(AphrontPanelView::WIDTH_WIDE);
|
||||||
|
$panel->appendChild($error_view);
|
||||||
|
$panel->appendChild($form);
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse(
|
||||||
|
$panel,
|
||||||
|
array(
|
||||||
|
'title' => $title,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
src/applications/owners/controller/edit/__init__.php
Normal file
26
src/applications/owners/controller/edit/__init__.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/404');
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/storage/package');
|
||||||
|
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||||
|
phutil_require_module('phabricator', 'applications/repository/storage/repository');
|
||||||
|
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||||
|
phutil_require_module('phabricator', 'infrastructure/javelin/api');
|
||||||
|
phutil_require_module('phabricator', 'view/control/typeahead');
|
||||||
|
phutil_require_module('phabricator', 'view/form/base');
|
||||||
|
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||||
|
phutil_require_module('phabricator', 'view/form/error');
|
||||||
|
phutil_require_module('phabricator', 'view/layout/panel');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorOwnersEditController.php');
|
|
@ -58,18 +58,42 @@ class PhabricatorOwnersListController extends PhabricatorOwnersController {
|
||||||
phutil_escape_html($name)));
|
phutil_escape_html($name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$package = new PhabricatorOwnersPackage();
|
||||||
|
|
||||||
switch ($this->view) {
|
switch ($this->view) {
|
||||||
case 'search':
|
case 'search':
|
||||||
$content = $this->renderPackageTable(array(), 'Search Results');
|
$packages = array();
|
||||||
|
|
||||||
|
$header = 'Search Results';
|
||||||
|
$nodata = 'No packages match your query.';
|
||||||
break;
|
break;
|
||||||
case 'owned':
|
case 'owned':
|
||||||
$content = $this->renderOwnedView();
|
$owner = new PhabricatorOwnersOwner();
|
||||||
|
$data = queryfx_all(
|
||||||
|
$package->establishConnection('r'),
|
||||||
|
'SELECT p.* FROM %T p JOIN %T o ON p.id = o.packageID
|
||||||
|
WHERE o.userPHID = %s GROUP BY p.id',
|
||||||
|
$package->getTableName(),
|
||||||
|
$owner->getTableName(),
|
||||||
|
$user->getPHID());
|
||||||
|
$packages = $package->loadAllFromArray($data);
|
||||||
|
|
||||||
|
$header = 'Owned Packages';
|
||||||
|
$nodata = 'No owned packages';
|
||||||
break;
|
break;
|
||||||
case 'all':
|
case 'all':
|
||||||
$content = $this->renderAllView();
|
$packages = $package->loadAll();
|
||||||
|
|
||||||
|
$header = 'All Packages';
|
||||||
|
$nodata = 'There are no defined packages.';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$content = $this->renderPackageTable(
|
||||||
|
$packages,
|
||||||
|
$header,
|
||||||
|
$nodata);
|
||||||
|
|
||||||
$filter = new AphrontListFilterView();
|
$filter = new AphrontListFilterView();
|
||||||
$filter->addButton(
|
$filter->addButton(
|
||||||
phutil_render_tag(
|
phutil_render_tag(
|
||||||
|
@ -127,26 +151,68 @@ class PhabricatorOwnersListController extends PhabricatorOwnersController {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderOwnedView() {
|
private function renderPackageTable(array $packages, $header, $nodata) {
|
||||||
$packages = array();
|
|
||||||
|
|
||||||
return $this->renderPackageTable($packages, 'Owned Packages');
|
if ($packages) {
|
||||||
}
|
$package_ids = mpull($packages, 'getID');
|
||||||
|
|
||||||
private function renderAllView() {
|
$owners = id(new PhabricatorOwnersOwner())->loadAllWhere(
|
||||||
$packages = array();
|
'packageID IN (%Ld)',
|
||||||
|
$package_ids);
|
||||||
|
|
||||||
return $this->renderPackageTable($packages, 'All Packages');
|
$paths = id(new PhabricatorOwnersPath())->loadAllWhere(
|
||||||
}
|
'packageID in (%Ld)',
|
||||||
|
$package_ids);
|
||||||
|
|
||||||
private function renderPackageTable(array $packages, $header) {
|
$phids = array();
|
||||||
|
foreach ($owners as $owner) {
|
||||||
|
$phids[$owner->getUserPHID()] = true;
|
||||||
|
}
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
$phids[$path->getRepositoryPHID()] = true;
|
||||||
|
}
|
||||||
|
$phids = array_keys($phids);
|
||||||
|
|
||||||
|
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||||
|
|
||||||
|
$owners = mgroup($owners, 'getPackageID');
|
||||||
|
$paths = mgroup($paths, 'getPackageID');
|
||||||
|
} else {
|
||||||
|
$handles = array();
|
||||||
|
$owners = array();
|
||||||
|
$paths = array();
|
||||||
|
}
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
foreach ($packages as $package) {
|
foreach ($packages as $package) {
|
||||||
|
|
||||||
|
$pkg_owners = idx($owners, $package->getID(), array());
|
||||||
|
foreach ($pkg_owners as $key => $owner) {
|
||||||
|
$pkg_owners[$key] = $handles[$owner->getUserPHID()]->renderLink();
|
||||||
|
if ($owner->getUserPHID() == $package->getPrimaryOwnerPHID()) {
|
||||||
|
$pkg_owners[$key] = '<strong>'.$pkg_owners[$key].'</strong>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$pkg_owners = implode('<br />', $pkg_owners);
|
||||||
|
|
||||||
|
$pkg_paths = idx($paths, $package->getID(), array());
|
||||||
|
foreach ($pkg_paths as $key => $path) {
|
||||||
|
$repo = $handles[$path->getRepositoryPHID()]->getName();
|
||||||
|
$pkg_paths[$key] =
|
||||||
|
'<strong>'.$repo.'</strong> '.
|
||||||
|
phutil_escape_html($path->getPath());
|
||||||
|
}
|
||||||
|
$pkg_paths = implode('<br />', $pkg_paths);
|
||||||
|
|
||||||
$rows[] = array(
|
$rows[] = array(
|
||||||
'x',
|
phutil_render_tag(
|
||||||
'y',
|
'a',
|
||||||
'z',
|
array(
|
||||||
|
'href' => '/owners/package/'.$package->getID().'/',
|
||||||
|
),
|
||||||
|
phutil_escape_html($package->getName())),
|
||||||
|
$pkg_owners,
|
||||||
|
$pkg_paths,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +225,7 @@ class PhabricatorOwnersListController extends PhabricatorOwnersController {
|
||||||
));
|
));
|
||||||
$table->setColumnClasses(
|
$table->setColumnClasses(
|
||||||
array(
|
array(
|
||||||
'',
|
'pri',
|
||||||
'',
|
'',
|
||||||
'wide wrap',
|
'wide wrap',
|
||||||
));
|
));
|
||||||
|
|
|
@ -7,7 +7,11 @@
|
||||||
|
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'applications/owners/controller/base');
|
phutil_require_module('phabricator', 'applications/owners/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/storage/owner');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/storage/package');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/storage/path');
|
||||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||||
|
phutil_require_module('phabricator', 'storage/queryfx');
|
||||||
phutil_require_module('phabricator', 'view/control/table');
|
phutil_require_module('phabricator', 'view/control/table');
|
||||||
phutil_require_module('phabricator', 'view/form/base');
|
phutil_require_module('phabricator', 'view/form/base');
|
||||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||||
|
|
|
@ -24,7 +24,7 @@ class PhabricatorOwnersOwner extends PhabricatorOwnersDAO {
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_TIMESTAMPS => false,
|
self::CONFIG_TIMESTAMPS => false,
|
||||||
);
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,16 +23,110 @@ class PhabricatorOwnersPackage extends PhabricatorOwnersDAO {
|
||||||
protected $description;
|
protected $description;
|
||||||
protected $primaryOwnerPHID;
|
protected $primaryOwnerPHID;
|
||||||
|
|
||||||
|
private $unsavedOwners;
|
||||||
|
private $unsavedPaths;
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
// This information is better available from the history table.
|
// This information is better available from the history table.
|
||||||
self::CONFIG_TIMESTAMPS => false,
|
self::CONFIG_TIMESTAMPS => false,
|
||||||
self::CONFIG_AUX_PHID => true,
|
self::CONFIG_AUX_PHID => true,
|
||||||
);
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generatePHID() {
|
public function generatePHID() {
|
||||||
return PhabricatorPHID::generateNew('OPKG');
|
return PhabricatorPHID::generateNewPHID('OPKG');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachUnsavedOwners(array $owners) {
|
||||||
|
$this->unsavedOwners = $owners;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachUnsavedPaths(array $paths) {
|
||||||
|
$this->unsavedPaths = $paths;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadOwners() {
|
||||||
|
if (!$this->getID()) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
return id(new PhabricatorOwnersOwner())->loadAllWhere(
|
||||||
|
'packageID = %d',
|
||||||
|
$this->getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadPaths() {
|
||||||
|
if (!$this->getID()) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
return id(new PhabricatorOwnersPath())->loadAllWhere(
|
||||||
|
'packageID = %d',
|
||||||
|
$this->getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function save() {
|
||||||
|
|
||||||
|
// TODO: Transactions!
|
||||||
|
|
||||||
|
$ret = parent::save();
|
||||||
|
|
||||||
|
if ($this->unsavedOwners) {
|
||||||
|
$new_owners = array_fill_keys($this->unsavedOwners, true);
|
||||||
|
$cur_owners = array();
|
||||||
|
foreach ($this->loadOwners() as $owner) {
|
||||||
|
if (empty($new_owners[$owner->getUserPHID()])) {
|
||||||
|
$owner->delete();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$cur_owners[$owner->getUserPHID()] = true;
|
||||||
|
}
|
||||||
|
$add_owners = array_diff_key($new_owners, $cur_owners);
|
||||||
|
foreach ($add_owners as $phid => $ignored) {
|
||||||
|
$owner = new PhabricatorOwnersOwner();
|
||||||
|
$owner->setPackageID($this->getID());
|
||||||
|
$owner->setUserPHID($phid);
|
||||||
|
$owner->save();
|
||||||
|
}
|
||||||
|
unset($this->unsavedOwners);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->unsavedPaths) {
|
||||||
|
$new_paths = igroup($this->unsavedPaths, 'repositoryPHID', 'path');
|
||||||
|
$cur_paths = $this->loadPaths();
|
||||||
|
foreach ($cur_paths as $key => $path) {
|
||||||
|
if (empty($new_paths[$path->getRepositoryPHID()][$path->getPath()])) {
|
||||||
|
$path->delete();
|
||||||
|
unset($cur_paths[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cur_paths = mgroup($cur_paths, 'getRepositoryPHID', 'getPath');
|
||||||
|
foreach ($new_paths as $repository_phid => $paths) {
|
||||||
|
foreach ($paths as $path => $ignored) {
|
||||||
|
if (empty($cur_paths[$repository_phid][$path])) {
|
||||||
|
$obj = new PhabricatorOwnersPath();
|
||||||
|
$obj->setPackageID($this->getID());
|
||||||
|
$obj->setRepositoryPHID($repository_phid);
|
||||||
|
$obj->setPath($path);
|
||||||
|
$obj->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($this->unsavedPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete() {
|
||||||
|
foreach ($this->loadOwners() as $owner) {
|
||||||
|
$owner->delete();
|
||||||
|
}
|
||||||
|
foreach ($this->loadPaths() as $path) {
|
||||||
|
$path->delete();
|
||||||
|
}
|
||||||
|
return parent::delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,11 @@
|
||||||
|
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'applications/owners/storage/base');
|
phutil_require_module('phabricator', 'applications/owners/storage/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/storage/owner');
|
||||||
|
phutil_require_module('phabricator', 'applications/owners/storage/path');
|
||||||
phutil_require_module('phabricator', 'applications/phid/storage/phid');
|
phutil_require_module('phabricator', 'applications/phid/storage/phid');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
phutil_require_source('PhabricatorOwnersPackage.php');
|
phutil_require_source('PhabricatorOwnersPackage.php');
|
||||||
|
|
|
@ -25,7 +25,7 @@ class PhabricatorOwnersPath extends PhabricatorOwnersDAO {
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_TIMESTAMPS => false,
|
self::CONFIG_TIMESTAMPS => false,
|
||||||
);
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,28 @@ class PhabricatorObjectHandleData {
|
||||||
$handles[$phid] = $handle;
|
$handles[$phid] = $handle;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PhabricatorPHIDConstants::PHID_TYPE_REPO:
|
||||||
|
$class = 'PhabricatorRepository';
|
||||||
|
PhutilSymbolLoader::loadClass($class);
|
||||||
|
$object = newv($class, array());
|
||||||
|
|
||||||
|
$repositories = $object->loadAllWhere('phid in (%Ls)', $phids);
|
||||||
|
$repositories = mpull($repositories, null, 'getPHID');
|
||||||
|
|
||||||
|
foreach ($phids as $phid) {
|
||||||
|
$handle = new PhabricatorObjectHandle();
|
||||||
|
$handle->setPHID($phid);
|
||||||
|
$handle->setType($type);
|
||||||
|
if (empty($repositories[$phid])) {
|
||||||
|
$handle->setName('Unknown Repository');
|
||||||
|
} else {
|
||||||
|
$repository = $repositories[$phid];
|
||||||
|
$handle->setName($repository->getCallsign());
|
||||||
|
$handle->setURI('/diffusion/'.$repository->getCallsign().'/');
|
||||||
|
}
|
||||||
|
$handles[$phid] = $handle;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
$loader = null;
|
$loader = null;
|
||||||
if (isset($external_loaders[$type])) {
|
if (isset($external_loaders[$type])) {
|
||||||
|
|
|
@ -22,20 +22,25 @@ final class AphrontPanelView extends AphrontView {
|
||||||
const WIDTH_FORM = 'form';
|
const WIDTH_FORM = 'form';
|
||||||
const WIDTH_WIDE = 'wide';
|
const WIDTH_WIDE = 'wide';
|
||||||
|
|
||||||
private $createButton;
|
private $buttons = array();
|
||||||
private $header;
|
private $header;
|
||||||
private $width;
|
private $width;
|
||||||
|
|
||||||
public function setCreateButton($create_button, $href) {
|
public function setCreateButton($create_button, $href) {
|
||||||
|
$this->addButton(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => $href,
|
||||||
|
'class' => 'button green',
|
||||||
|
),
|
||||||
|
$create_button));
|
||||||
|
|
||||||
$this->createButton = phutil_render_tag(
|
return $this;
|
||||||
'a',
|
}
|
||||||
array(
|
|
||||||
'href' => $href,
|
|
||||||
'class' => 'create-button button green',
|
|
||||||
),
|
|
||||||
$create_button);
|
|
||||||
|
|
||||||
|
public function addButton($button) {
|
||||||
|
$this->buttons[] = $button;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,10 +61,12 @@ final class AphrontPanelView extends AphrontView {
|
||||||
$header = null;
|
$header = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->createButton !== null) {
|
$buttons = null;
|
||||||
$button = $this->createButton;
|
if ($this->buttons) {
|
||||||
} else {
|
$buttons =
|
||||||
$button = null;
|
'<div class="aphront-panel-view-buttons">'.
|
||||||
|
implode(" ", $this->buttons).
|
||||||
|
'</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = $this->renderChildren();
|
$table = $this->renderChildren();
|
||||||
|
@ -73,7 +80,7 @@ final class AphrontPanelView extends AphrontView {
|
||||||
|
|
||||||
return
|
return
|
||||||
'<div class="'.implode(' ', $class).'">'.
|
'<div class="'.implode(' ', $class).'">'.
|
||||||
$button.
|
$buttons.
|
||||||
$header.
|
$header.
|
||||||
$table.
|
$table.
|
||||||
'</div>';
|
'</div>';
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
background: #f6f6f6;
|
background: #f6f6f6;
|
||||||
border-bottom: 1px solid #bbbbbb;
|
border-bottom: 1px solid #bbbbbb;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
margin-bottom: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.aphront-list-filter-view-buttons {
|
.aphront-list-filter-view-buttons {
|
||||||
|
@ -24,7 +25,7 @@
|
||||||
|
|
||||||
.aphront-list-filter-view-controls .aphront-form-view {
|
.aphront-list-filter-view-controls .aphront-form-view {
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
padding: 0 0 6px;
|
padding: 12px 0 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.aphront-list-filter-view-controls .aphront-form-view .aphront-form-label {
|
.aphront-list-filter-view-controls .aphront-form-view .aphront-form-label {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
padding: 2px 0 8px;
|
padding: 2px 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.aphront-panel-view a.create-button {
|
.aphront-panel-view-buttons {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue