diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index 7a7b02df22..652e0d697f 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -1,197 +1,197 @@ array( 'path' => '/res/771b987d/rsrc/css/aphront/dialog-view.css', 'type' => 'css', 'requires' => array( ), ), 'aphront-form-view-css' => array( - 'path' => '/res/75636a53/rsrc/css/aphront/form-view.css', + 'path' => '/res/785ac1c6/rsrc/css/aphront/form-view.css', 'type' => 'css', 'requires' => array( ), ), 'aphront-panel-view-css' => array( 'path' => '/res/fe62e634/rsrc/css/aphront/panel-view.css', 'type' => 'css', 'requires' => array( ), ), 'aphront-side-nav-view-css' => array( - 'path' => '/res/1a16f19a/rsrc/css/aphront/side-nav-view.css', + 'path' => '/res/0fc0545c/rsrc/css/aphront/side-nav-view.css', 'type' => 'css', 'requires' => array( ), ), 'aphront-table-view-css' => array( 'path' => '/res/52b0191f/rsrc/css/aphront/table-view.css', 'type' => 'css', 'requires' => array( ), ), 'aphront-tokenizer-control-css' => array( 'path' => '/res/a3d23074/rsrc/css/aphront/tokenizer.css', 'type' => 'css', 'requires' => array( 0 => 'aphront-typeahead-control-css', ), ), 'aphront-typeahead-control-css' => array( 'path' => '/res/928df9f0/rsrc/css/aphront/typeahead.css', 'type' => 'css', 'requires' => array( ), ), 'phabricator-standard-page-view' => array( - 'path' => '/res/0eef6905/rsrc/css/application/base/standard-page-view.css', + 'path' => '/res/1f93ada7/rsrc/css/application/base/standard-page-view.css', 'type' => 'css', 'requires' => array( ), ), 'differential-changeset-view-css' => array( 'path' => '/res/658d181a/rsrc/css/application/differential/changeset-view.css', 'type' => 'css', 'requires' => array( ), ), 'differential-core-view-css' => array( 'path' => '/res/f750b85d/rsrc/css/application/differential/core.css', 'type' => 'css', 'requires' => array( ), ), 'differential-table-of-contents-css' => array( 'path' => '/res/ebf6641c/rsrc/css/application/differential/table-of-contents.css', 'type' => 'css', 'requires' => array( ), ), 'phabricator-directory-css' => array( 'path' => '/res/6a000601/rsrc/css/application/directory/phabricator-directory.css', 'type' => 'css', 'requires' => array( ), ), 'phabricator-core-buttons-css' => array( 'path' => '/res/6e348ba4/rsrc/css/core/buttons.css', 'type' => 'css', 'requires' => array( ), ), 'phabricator-core-css' => array( 'path' => '/res/39ce37c2/rsrc/css/core/core.css', 'type' => 'css', 'requires' => array( ), ), 'syntax-highlighting-css' => array( 'path' => '/res/fb673ece/rsrc/css/core/syntax.css', 'type' => 'css', 'requires' => array( ), ), 'javelin-behavior-aphront-basic-tokenizer' => array( 'path' => '/res/8317d761/rsrc/js/application/core/behavior-tokenizer.js', 'type' => 'js', 'requires' => array( 0 => 'javelin-lib-dev', ), ), 'javelin-behavior-differential-populate' => array( 'path' => '/res/9982573c/rsrc/js/application/differential/behavior-populate.js', 'type' => 'js', 'requires' => array( 0 => 'javelin-lib-dev', ), ), 'javelin-init-dev' => array( 'path' => '/res/c57a9e89/rsrc/js/javelin/init.dev.js', 'type' => 'js', 'requires' => array( ), ), 'javelin-init-prod' => array( 'path' => '/res/f0172c54/rsrc/js/javelin/init.min.js', 'type' => 'js', 'requires' => array( ), ), 'javelin-lib-dev' => array( 'path' => '/res/3e747182/rsrc/js/javelin/javelin.dev.js', 'type' => 'js', 'requires' => array( ), ), 'javelin-lib-prod' => array( 'path' => '/res/9438670e/rsrc/js/javelin/javelin.min.js', 'type' => 'js', 'requires' => array( ), ), 'javelin-typeahead-dev' => array( 'path' => '/res/c81c0f01/rsrc/js/javelin/typeahead.dev.js', 'type' => 'js', 'requires' => array( ), ), 'javelin-typeahead-prod' => array( 'path' => '/res/1da2d984/rsrc/js/javelin/typeahead.min.js', 'type' => 'js', 'requires' => array( ), ), )); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 9d9939698c..cca9234785 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1,296 +1,298 @@ array( 'Aphront404Response' => 'aphront/response/404', 'AphrontAjaxResponse' => 'aphront/response/ajax', 'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration', 'AphrontController' => 'aphront/controller', 'AphrontDatabaseConnection' => 'storage/connection/base', 'AphrontDefaultApplicationConfiguration' => 'aphront/default/configuration', 'AphrontDefaultApplicationController' => 'aphront/default/controller', 'AphrontDialogResponse' => 'aphront/response/dialog', 'AphrontDialogView' => 'view/dialog', 'AphrontErrorView' => 'view/form/error', 'AphrontException' => 'aphront/exception/base', 'AphrontFileResponse' => 'aphront/response/file', 'AphrontFormCheckboxControl' => 'view/form/control/checkbox', 'AphrontFormControl' => 'view/form/control/base', 'AphrontFormFileControl' => 'view/form/control/file', 'AphrontFormMarkupControl' => 'view/form/control/markup', 'AphrontFormSelectControl' => 'view/form/control/select', 'AphrontFormStaticControl' => 'view/form/control/static', 'AphrontFormSubmitControl' => 'view/form/control/submit', 'AphrontFormTextAreaControl' => 'view/form/control/textarea', 'AphrontFormTextControl' => 'view/form/control/text', 'AphrontFormTokenizerControl' => 'view/form/control/tokenizer', 'AphrontFormView' => 'view/form/base', 'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql', 'AphrontNullView' => 'view/null', 'AphrontPageView' => 'view/page/base', 'AphrontPanelView' => 'view/layout/panel', 'AphrontQueryConnectionException' => 'storage/exception/connection', 'AphrontQueryConnectionLostException' => 'storage/exception/connectionlost', 'AphrontQueryCountException' => 'storage/exception/count', 'AphrontQueryException' => 'storage/exception/base', 'AphrontQueryObjectMissingException' => 'storage/exception/objectmissing', 'AphrontQueryParameterException' => 'storage/exception/parameter', 'AphrontQueryRecoverableException' => 'storage/exception/recoverable', 'AphrontRedirectException' => 'aphront/exception/redirect', 'AphrontRedirectResponse' => 'aphront/response/redirect', 'AphrontRequest' => 'aphront/request', 'AphrontResponse' => 'aphront/response/base', 'AphrontSideNavView' => 'view/layout/sidenav', 'AphrontTableView' => 'view/control/table', 'AphrontURIMapper' => 'aphront/mapper', 'AphrontView' => 'view/base', 'AphrontWebpageResponse' => 'aphront/response/webpage', 'CelerityAPI' => 'infratructure/celerity/api', 'CelerityResourceController' => 'infratructure/celerity/controller', 'CelerityResourceMap' => 'infratructure/celerity/map', 'CelerityStaticResourceResponse' => 'infratructure/celerity/response', 'ConduitAPIMethod' => 'applications/conduit/method/base', 'ConduitAPIRequest' => 'applications/conduit/protocol/request', 'ConduitAPI_conduit_connect_Method' => 'applications/conduit/method/conduit/connect', 'ConduitAPI_differential_creatediff_Method' => 'applications/conduit/method/differential/creatediff', 'ConduitAPI_differential_setdiffproperty_Method' => 'applications/conduit/method/differential/setdiffproperty', 'ConduitAPI_file_upload_Method' => 'applications/conduit/method/file/upload', 'ConduitAPI_user_find_Method' => 'applications/conduit/method/user/find', 'ConduitException' => 'applications/conduit/protocol/exception', 'DifferentialAction' => 'applications/differential/constants/action', 'DifferentialCCWelcomeMail' => 'applications/differential/mail/ccwelcome', 'DifferentialChangeType' => 'applications/differential/constants/changetype', 'DifferentialChangeset' => 'applications/differential/storage/changeset', 'DifferentialChangesetDetailView' => 'applications/differential/view/changesetdetailview', 'DifferentialChangesetListView' => 'applications/differential/view/changesetlistview', 'DifferentialChangesetParser' => 'applications/differential/parser/changeset', 'DifferentialChangesetViewController' => 'applications/differential/controller/changesetview', 'DifferentialController' => 'applications/differential/controller/base', 'DifferentialDAO' => 'applications/differential/storage/base', 'DifferentialDiff' => 'applications/differential/storage/diff', 'DifferentialDiffContentMail' => 'applications/differential/mail/diffcontent', 'DifferentialDiffProperty' => 'applications/differential/storage/diffproperty', 'DifferentialDiffTableOfContentsView' => 'applications/differential/view/difftableofcontents', 'DifferentialDiffViewController' => 'applications/differential/controller/diffview', 'DifferentialFeedbackMail' => 'applications/differential/mail/feedback', 'DifferentialHunk' => 'applications/differential/storage/hunk', 'DifferentialLintStatus' => 'applications/differential/constants/lintstatus', 'DifferentialMail' => 'applications/differential/mail/base', 'DifferentialNewDiffMail' => 'applications/differential/mail/newdiff', 'DifferentialReviewRequestMail' => 'applications/differential/mail/reviewrequest', 'DifferentialRevision' => 'applications/differential/storage/revision', 'DifferentialRevisionControlSystem' => 'applications/differential/constants/revisioncontrolsystem', 'DifferentialRevisionEditController' => 'applications/differential/controller/revisionedit', 'DifferentialRevisionEditor' => 'applications/differential/editor/revision', 'DifferentialRevisionListController' => 'applications/differential/controller/revisionlist', + 'DifferentialRevisionListData' => 'applications/differential/data/revisionlist', 'DifferentialRevisionStatus' => 'applications/differential/constants/revisionstatus', 'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus', 'Javelin' => 'infratructure/javelin/api', 'LiskDAO' => 'storage/lisk/dao', 'PhabricatorAuthController' => 'applications/auth/controlller/base', 'PhabricatorConduitAPIController' => 'applications/conduit/controller/api', 'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/connectionlog', 'PhabricatorConduitConsoleController' => 'applications/conduit/controller/console', 'PhabricatorConduitController' => 'applications/conduit/controller/base', 'PhabricatorConduitDAO' => 'applications/conduit/storage/base', 'PhabricatorConduitLogController' => 'applications/conduit/controller/log', 'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/methodcalllog', 'PhabricatorController' => 'applications/base/controller/base', 'PhabricatorDirectoryCategory' => 'applications/directory/storage/category', 'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete', 'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit', 'PhabricatorDirectoryCategoryListController' => 'applications/directory/controller/categorylist', 'PhabricatorDirectoryController' => 'applications/directory/controller/base', 'PhabricatorDirectoryDAO' => 'applications/directory/storage/base', 'PhabricatorDirectoryItem' => 'applications/directory/storage/item', 'PhabricatorDirectoryItemDeleteController' => 'applications/directory/controller/itemdelete', 'PhabricatorDirectoryItemEditController' => 'applications/directory/controller/itemedit', 'PhabricatorDirectoryItemListController' => 'applications/directory/controller/itemlist', 'PhabricatorDirectoryMainController' => 'applications/directory/controller/main', 'PhabricatorFile' => 'applications/files/storage/file', 'PhabricatorFileController' => 'applications/files/controller/base', 'PhabricatorFileDAO' => 'applications/files/storage/base', 'PhabricatorFileListController' => 'applications/files/controller/list', 'PhabricatorFileStorageBlob' => 'applications/files/storage/storageblob', 'PhabricatorFileURI' => 'applications/files/uri', 'PhabricatorFileUploadController' => 'applications/files/controller/upload', 'PhabricatorFileViewController' => 'applications/files/controller/view', 'PhabricatorLiskDAO' => 'applications/base/storage/lisk', 'PhabricatorLoginController' => 'applications/auth/controlller/login', 'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/base', 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/phpmailerlite', 'PhabricatorMetaMTAController' => 'applications/metamta/controller/base', 'PhabricatorMetaMTADAO' => 'applications/metamta/storage/base', 'PhabricatorMetaMTAListController' => 'applications/metamta/controller/list', 'PhabricatorMetaMTAMail' => 'applications/metamta/storage/mail', 'PhabricatorMetaMTAMailingList' => 'applications/metamta/storage/mailinglist', 'PhabricatorMetaMTAMailingListEditController' => 'applications/metamta/controller/mailinglistedit', 'PhabricatorMetaMTAMailingListsController' => 'applications/metamta/controller/mailinglists', 'PhabricatorMetaMTASendController' => 'applications/metamta/controller/send', 'PhabricatorMetaMTAViewController' => 'applications/metamta/controller/view', 'PhabricatorObjectHandle' => 'applications/phid/handle', 'PhabricatorObjectHandleData' => 'applications/phid/handle/data', 'PhabricatorPHID' => 'applications/phid/storage/phid', 'PhabricatorPHIDAllocateController' => 'applications/phid/controller/allocate', 'PhabricatorPHIDController' => 'applications/phid/controller/base', 'PhabricatorPHIDDAO' => 'applications/phid/storage/base', 'PhabricatorPHIDListController' => 'applications/phid/controller/list', 'PhabricatorPHIDLookupController' => 'applications/phid/controller/lookup', 'PhabricatorPHIDType' => 'applications/phid/storage/type', 'PhabricatorPHIDTypeEditController' => 'applications/phid/controller/typeedit', 'PhabricatorPHIDTypeListController' => 'applications/phid/controller/typelist', 'PhabricatorPeopleController' => 'applications/people/controller/base', 'PhabricatorPeopleEditController' => 'applications/people/controller/edit', 'PhabricatorPeopleListController' => 'applications/people/controller/list', 'PhabricatorPeopleProfileController' => 'applications/people/controller/profile', 'PhabricatorStandardPageView' => 'view/page/standard', 'PhabricatorTypeaheadCommonDatasourceController' => 'applications/typeahead/controller/common', 'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/base', 'PhabricatorUser' => 'applications/people/storage/user', 'PhabricatorUserDAO' => 'applications/people/storage/base', ), 'function' => array( '_qsprintf_check_scalar_type' => 'storage/qsprintf', '_qsprintf_check_type' => 'storage/qsprintf', 'celerity_generate_unique_node_id' => 'infratructure/celerity/api', 'celerity_register_resource_map' => 'infratructure/celerity/map', 'javelin_render_tag' => 'infratructure/javelin/markup', 'qsprintf' => 'storage/qsprintf', 'queryfx' => 'storage/queryfx', 'queryfx_all' => 'storage/queryfx', 'queryfx_one' => 'storage/queryfx', 'require_celerity_resource' => 'infratructure/celerity/api', 'vqsprintf' => 'storage/qsprintf', 'vqueryfx' => 'storage/queryfx', + 'vqueryfx_all' => 'storage/queryfx', 'xsprintf_query' => 'storage/qsprintf', ), 'requires_class' => array( 'Aphront404Response' => 'AphrontResponse', 'AphrontAjaxResponse' => 'AphrontResponse', 'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration', 'AphrontDefaultApplicationController' => 'AphrontController', 'AphrontDialogResponse' => 'AphrontResponse', 'AphrontDialogView' => 'AphrontView', 'AphrontErrorView' => 'AphrontView', 'AphrontFileResponse' => 'AphrontResponse', 'AphrontFormCheckboxControl' => 'AphrontFormControl', 'AphrontFormControl' => 'AphrontView', 'AphrontFormFileControl' => 'AphrontFormControl', 'AphrontFormMarkupControl' => 'AphrontFormControl', 'AphrontFormSelectControl' => 'AphrontFormControl', 'AphrontFormStaticControl' => 'AphrontFormControl', 'AphrontFormSubmitControl' => 'AphrontFormControl', 'AphrontFormTextAreaControl' => 'AphrontFormControl', 'AphrontFormTextControl' => 'AphrontFormControl', 'AphrontFormTokenizerControl' => 'AphrontFormControl', 'AphrontFormView' => 'AphrontView', 'AphrontMySQLDatabaseConnection' => 'AphrontDatabaseConnection', 'AphrontNullView' => 'AphrontView', 'AphrontPageView' => 'AphrontView', 'AphrontPanelView' => 'AphrontView', 'AphrontQueryConnectionException' => 'AphrontQueryException', 'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException', 'AphrontQueryCountException' => 'AphrontQueryException', 'AphrontQueryObjectMissingException' => 'AphrontQueryException', 'AphrontQueryParameterException' => 'AphrontQueryException', 'AphrontQueryRecoverableException' => 'AphrontQueryException', 'AphrontRedirectException' => 'AphrontException', 'AphrontRedirectResponse' => 'AphrontResponse', 'AphrontSideNavView' => 'AphrontView', 'AphrontTableView' => 'AphrontView', 'AphrontWebpageResponse' => 'AphrontResponse', 'CelerityResourceController' => 'AphrontController', 'ConduitAPI_conduit_connect_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_creatediff_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod', 'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod', 'ConduitAPI_user_find_Method' => 'ConduitAPIMethod', 'DifferentialCCWelcomeMail' => 'DifferentialReviewRequestMail', 'DifferentialChangeset' => 'DifferentialDAO', 'DifferentialChangesetDetailView' => 'AphrontView', 'DifferentialChangesetListView' => 'AphrontView', 'DifferentialChangesetViewController' => 'DifferentialController', 'DifferentialController' => 'PhabricatorController', 'DifferentialDAO' => 'PhabricatorLiskDAO', 'DifferentialDiff' => 'DifferentialDAO', 'DifferentialDiffContentMail' => 'DifferentialMail', 'DifferentialDiffProperty' => 'DifferentialDAO', 'DifferentialDiffTableOfContentsView' => 'AphrontView', 'DifferentialDiffViewController' => 'DifferentialController', 'DifferentialFeedbackMail' => 'DifferentialMail', 'DifferentialHunk' => 'DifferentialDAO', 'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail', 'DifferentialReviewRequestMail' => 'DifferentialMail', 'DifferentialRevision' => 'DifferentialDAO', 'DifferentialRevisionEditController' => 'DifferentialController', 'DifferentialRevisionListController' => 'DifferentialController', 'PhabricatorAuthController' => 'PhabricatorController', 'PhabricatorConduitAPIController' => 'PhabricatorConduitController', 'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO', 'PhabricatorConduitConsoleController' => 'PhabricatorConduitController', 'PhabricatorConduitController' => 'PhabricatorController', 'PhabricatorConduitDAO' => 'PhabricatorLiskDAO', 'PhabricatorConduitLogController' => 'PhabricatorConduitController', 'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO', 'PhabricatorController' => 'AphrontController', 'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO', 'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryCategoryListController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryController' => 'PhabricatorController', 'PhabricatorDirectoryDAO' => 'PhabricatorLiskDAO', 'PhabricatorDirectoryItem' => 'PhabricatorDirectoryDAO', 'PhabricatorDirectoryItemDeleteController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryItemListController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController', 'PhabricatorFile' => 'PhabricatorFileDAO', 'PhabricatorFileController' => 'PhabricatorController', 'PhabricatorFileDAO' => 'PhabricatorLiskDAO', 'PhabricatorFileListController' => 'PhabricatorFileController', 'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO', 'PhabricatorFileUploadController' => 'PhabricatorFileController', 'PhabricatorFileViewController' => 'PhabricatorFileController', 'PhabricatorLiskDAO' => 'LiskDAO', 'PhabricatorLoginController' => 'PhabricatorAuthController', 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMetaMTAController' => 'PhabricatorController', 'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO', 'PhabricatorMetaMTAListController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAMailingList' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAMailingListEditController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMailingListsController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTASendController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAViewController' => 'PhabricatorMetaMTAController', 'PhabricatorPHID' => 'PhabricatorPHIDDAO', 'PhabricatorPHIDAllocateController' => 'PhabricatorPHIDController', 'PhabricatorPHIDController' => 'PhabricatorController', 'PhabricatorPHIDDAO' => 'PhabricatorLiskDAO', 'PhabricatorPHIDListController' => 'PhabricatorPHIDController', 'PhabricatorPHIDLookupController' => 'PhabricatorPHIDController', 'PhabricatorPHIDType' => 'PhabricatorPHIDDAO', 'PhabricatorPHIDTypeEditController' => 'PhabricatorPHIDController', 'PhabricatorPHIDTypeListController' => 'PhabricatorPHIDController', 'PhabricatorPeopleController' => 'PhabricatorController', 'PhabricatorPeopleEditController' => 'PhabricatorPeopleController', 'PhabricatorPeopleListController' => 'PhabricatorPeopleController', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', 'PhabricatorStandardPageView' => 'AphrontPageView', 'PhabricatorTypeaheadCommonDatasourceController' => 'PhabricatorTypeaheadDatasourceController', 'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController', 'PhabricatorUser' => 'PhabricatorUserDAO', 'PhabricatorUserDAO' => 'PhabricatorLiskDAO', ), 'requires_interface' => array( ), )); diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php index 2cbc9e30f8..3c76065a09 100644 --- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php +++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php @@ -1,156 +1,157 @@ array( '$' => 'RepositoryListController', 'new/$' => 'RepositoryEditController', 'edit/(?\d+)/$' => 'RepositoryEditController', 'delete/(?\d+)/$' => 'RepositoryDeleteController', ), '/' => array( '$' => 'PhabricatorDirectoryMainController', ), '/directory/' => array( 'item/$' => 'PhabricatorDirectoryItemListController', 'item/edit/(?:(?\d+)/)?$' => 'PhabricatorDirectoryItemEditController', 'item/delete/(?\d+)/' => 'PhabricatorDirectoryItemDeleteController', 'category/$' => 'PhabricatorDirectoryCategoryListController', 'category/edit/(?:(?\d+)/)?$' => 'PhabricatorDirectoryCategoryEditController', 'category/delete/(?\d+)/' => 'PhabricatorDirectoryCategoryDeleteController', ), '/file/' => array( '$' => 'PhabricatorFileListController', 'upload/$' => 'PhabricatorFileUploadController', '(?info)/(?[^/]+)/' => 'PhabricatorFileViewController', '(?view)/(?[^/]+)/' => 'PhabricatorFileViewController', '(?download)/(?[^/]+)/' => 'PhabricatorFileViewController', ), '/phid/' => array( '$' => 'PhabricatorPHIDLookupController', 'list/$' => 'PhabricatorPHIDListController', 'type/$' => 'PhabricatorPHIDTypeListController', 'type/edit/(?:(?\d+)/)?$' => 'PhabricatorPHIDTypeEditController', 'new/$' => 'PhabricatorPHIDAllocateController', ), '/people/' => array( '$' => 'PhabricatorPeopleListController', 'edit/(?:(?\w+)/)?$' => 'PhabricatorPeopleEditController', ), '/p/(?\w+)/$' => 'PhabricatorPeopleProfileController', '/conduit/' => array( '$' => 'PhabricatorConduitConsoleController', 'method/(?[^/]+)$' => 'PhabricatorConduitConsoleController', 'log/$' => 'PhabricatorConduitLogController', ), '/api/(?[^/]+)$' => 'PhabricatorConduitAPIController', '/differential/' => array( '$' => 'DifferentialRevisionListController', + 'filter/(?\w+)/$' => 'DifferentialRevisionListController', 'diff/(?\d+)/$' => 'DifferentialDiffViewController', 'changeset/(?\d+)/$' => 'DifferentialChangesetViewController', 'revision/edit/(?:(?\d+)/)?$' => 'DifferentialRevisionEditController', ), '/res/' => array( '(?[a-f0-9]{8})/(?.+\.(?:css|js))$' => 'CelerityResourceController', ), '/typeahead/' => array( 'common/(?\w+)/$' => 'PhabricatorTypeaheadCommonDatasourceController', ), '/mail/' => array( '$' => 'PhabricatorMetaMTAListController', 'send/$' => 'PhabricatorMetaMTASendController', 'view/(?\d+)/$' => 'PhabricatorMetaMTAViewController', 'lists/$' => 'PhabricatorMetaMTAMailingListsController', 'lists/edit/(?:(?\d+)/)?$' => 'PhabricatorMetaMTAMailingListEditController', ), '/login/' => 'PhabricatorLoginController', ); } public function buildRequest() { $request = new AphrontRequest($this->getHost(), $this->getPath()); $request->setRequestData($_GET + $_POST); return $request; } public function handleException(Exception $ex) { $class = phutil_escape_html(get_class($ex)); $message = phutil_escape_html($ex->getMessage()); $content = '
'. '

Unhandled Exception "'.$class.'": '.$message.'

'. ''.phutil_escape_html((string)$ex).''. '
'; $view = new PhabricatorStandardPageView(); $view->appendChild($content); $response = new AphrontWebpageResponse(); $response->setContent($view->render()); return $response; } public function willSendResponse(AphrontResponse $response) { $request = $this->getRequest(); if ($response instanceof AphrontDialogResponse) { if (!$request->isAjax()) { $view = new PhabricatorStandardPageView(); $view->appendChild( '
'. $response->buildResponseString(). '
'); $response = new AphrontWebpageResponse(); $response->setContent($view->render()); return $response; } } return $response; } } diff --git a/src/aphront/response/base/AphrontResponse.php b/src/aphront/response/base/AphrontResponse.php index d632faba80..29a371c08d 100644 --- a/src/aphront/response/base/AphrontResponse.php +++ b/src/aphront/response/base/AphrontResponse.php @@ -1,48 +1,61 @@ request = $request; return $this; } public function getRequest() { return $this->request; } public function getHeaders() { return array(); } + + public function setCacheDurationInSeconds($duration) { + $this->cacheable = $duration; + return $this; + } public function getCacheHeaders() { - return array( - array('Cache-Control', 'private, no-cache, no-store, must-revalidate'), - array('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT'), - ); + if ($this->cacheable) { + $epoch = time() + $this->cacheable; + return array( + array('Expires', gmdate('D, d M Y H:i:s', $epoch) . ' GMT'), + ); + } else { + return array( + array('Cache-Control', 'private, no-cache, no-store, must-revalidate'), + array('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT'), + ); + } } abstract public function buildResponseString(); } diff --git a/src/applications/differential/controller/revisionlist/DifferentialRevisionListController.php b/src/applications/differential/controller/revisionlist/DifferentialRevisionListController.php index 2a1bb6c89d..60ad7d3143 100644 --- a/src/applications/differential/controller/revisionlist/DifferentialRevisionListController.php +++ b/src/applications/differential/controller/revisionlist/DifferentialRevisionListController.php @@ -1,40 +1,190 @@ filter = idx($data, 'filter'); + } + public function processRequest() { - $side_nav = new AphrontSideNavView(); - $side_nav->addNavItem( - phutil_render_tag( - 'a', - array( - 'href' => '/differential/', + $filters = array( + 'active' => array( + 'name' => 'Active Revisions', + 'queries' => array( + array( + 'query' + => DifferentialRevisionListData::QUERY_NEED_ACTION_FROM_SELF, + 'header' => 'Action Required', + 'nodata' => 'You have no revisions requiring action.', + ), + array( + 'query' + => DifferentialRevisionListData::QUERY_NEED_ACTION_FROM_OTHERS, + 'header' => 'Waiting on Others', + 'nodata' => 'You have no revisions waiting on others', + ), + ), + ), + 'open' => array( + 'name' => 'Open Revisions', + 'queries' => array( + array( + 'query' => DifferentialRevisionListData::QUERY_OPEN_OWNED, + 'header' => 'Open Revisions', + ), + ), + ), + 'reviews' => array( + 'name' => 'Open Reviews', + 'queries' => array( + array( + 'query' => DifferentialRevisionListData::QUERY_OPEN_REVIEWER, + 'header' => 'Open Reviews', + ), + ), + ), + 'all' => array( + 'name' => 'All Revisions', + 'queries' => array( + array( + 'query' => DifferentialRevisionListData::QUERY_OWNED, + 'header' => 'All Revisions', + ), ), - 'Active Revisions')); + ), + 'related' => array( + 'name' => 'All Revisions and Reviews', + 'queries' => array( + array( + 'query' => DifferentialRevisionListData::QUERY_OWNED_OR_REVIEWER, + 'header' => 'All Revisions and Reviews', + ), + ), + ), + ); + + if (empty($filters[$this->filter])) { + $this->filter = key($filters); + } + + $request = $this->getRequest(); + $user = $request->getUser(); + + $queries = array(); + $filter = $filters[$this->filter]; + foreach ($filter['queries'] as $query) { + $query_object = new DifferentialRevisionListData( + $query['query'], + array($user->getPHID())); + $queries[] = array( + 'object' => $query_object, + ) + $query; + } + + $side_nav = new AphrontSideNavView(); + foreach ($filters as $filter_name => $filter_desc) { + $selected = ($filter_name == $this->filter); + $side_nav->addNavItem( + phutil_render_tag( + 'a', + array( + 'href' => '/differential/filter/'.$filter_name.'/', + 'class' => $selected ? 'aphront-side-nav-selected' : null, + ), + phutil_escape_html($filter_desc['name']))); + } + foreach ($queries as $query) { + $table = $this->renderRevisionTable( + $query['object']->loadRevisions(), + $query['header'], + idx($query, 'nodata')); + $side_nav->appendChild($table); + } return $this->buildStandardPageResponse( $side_nav, array( 'title' => 'Differential Home', )); } + private function renderRevisionTable(array $revisions, $header, $nodata) { + + $rows = array(); + foreach ($revisions as $revision) { + $status = DifferentialRevisionStatus::getNameForRevisionStatus( + $revision->getStatus()); + + $rows[] = array( + 'D'.$revision->getID(), + phutil_render_tag( + 'a', + array( + 'href' => '/D'.$revision->getID(), + ), + phutil_escape_html($revision->getTitle())), + phutil_escape_html($status), + number_format($revision->getLineCount()), + $revision->getOwnerPHID(), + 'TODO', + $revision->getDateModified(), + $revision->getDateCreated(), + ); + } + + $table = new AphrontTableView($rows); + $table->setHeaders( + array( + 'ID', + 'Revision', + 'Status', + 'Lines', + 'Author', + 'Reviewers', + 'Updated', + 'Created', + )); + $table->setColumnClasses( + array( + null, + 'wide', + null, + null, + null, + null, + null, + null, + )); + if ($nodata !== null) { + $table->setNoDataString($nodata); + } + + + $panel = new AphrontPanelView(); + $panel->setHeader($header); + $panel->appendChild($table); + + return $panel; + } + } diff --git a/src/applications/differential/controller/revisionlist/__init__.php b/src/applications/differential/controller/revisionlist/__init__.php index e77e5b621b..8f45af9de8 100644 --- a/src/applications/differential/controller/revisionlist/__init__.php +++ b/src/applications/differential/controller/revisionlist/__init__.php @@ -1,15 +1,20 @@ filter = $filter; + $this->ids = $ids; + } + + public function getRevisions() { + return $this->revisions; + } + + public function setOrder($order) { + $this->order = $order; + return $this; + } + + public function loadRevisions() { + switch ($this->filter) { + case self::QUERY_CC: + $this->revisions = $this->loadAllOpenWithCCs($this->ids); + break; + case self::QUERY_ALL_OPEN: + $this->revisions = $this->loadAllOpen(); + break; + case self::QUERY_OPEN_OWNED: + $this->revisions = $this->loadAllWhere( + 'revision.status in (%Ld) AND revision.ownerPHID in (%Ls)', + $this->getOpenStatuses(), + $this->ids); + break; + case self::QUERY_COMMITTABLE: + $this->revisions = $this->loadAllWhere( + 'revision.status in (%Ld) AND revision.ownerPHID in (%Ls)', + array( + DifferentialRevisionStatus::ACCEPTED, + ), + $this->ids); + break; + case self::QUERY_REVISION_IDS: + $this->revisions = $this->loadAllWhere( + 'id in (%Ld)', + $this->ids); + break; + case self::QUERY_OPEN_REVIEWER: + $this->revisions = $this->loadAllWhereJoinReview( + 'revision.status in (%Ld) AND relationship.objectPHID in (%Ls)', + $this->getOpenStatuses(), + $this->ids); + break; + case self::QUERY_OWNED: + $this->revisions = $this->loadAllWhere( + 'revision.ownerPHID in (%Ls)', + $this->ids); + break; + case self::QUERY_OWNED_OR_REVIEWER: + $this->revisions = $this->loadAllWhereJoinReview( + 'revision.ownerPHID in (%Ls) OR relationship.objectPHID in (%Ls)', + $this->ids, + $this->ids); + break; + case self::QUERY_NEED_ACTION_FROM_SELF: + $rev = new DifferentialRevision(); + $data = queryfx_all( + $rev->establishConnection('r'), + 'SELECT revision.* FROM %T revision + WHERE revision.ownerPHID in (%Ls) + AND revision.status in (%Ld) + + UNION ALL + + SELECT revision.* FROM %T revision JOIN %T relationship + ON relationship.revisionID = revision.id + AND relationship.relation = %s + AND relationship.forbidden = 0 + WHERE relationship.objectPHID IN (%Ls) + AND revision.status in (%Ld) + + %Q', + $rev->getTableName(), + $this->ids, + array( + DifferentialRevisionStatus::NEEDS_REVISION, + DifferentialRevisionStatus::ACCEPTED, + ), + $rev->getTableName(), + DifferentialRevision::RELATIONSHIP_TABLE, + DifferentialRevision::RELATION_REVIEWER, + $this->ids, + array( + DifferentialRevisionStatus::NEEDS_REVIEW, + ), + $this->getOrderClause()); + + $data = ipull($data, null, 'id'); + $this->revisions = $rev->loadAllFromArray($data); + break; + case self::QUERY_NEED_ACTION_FROM_OTHERS: + $rev = new DifferentialRevision(); + $data = queryfx_all( + $rev->establishConnection('r'), + 'SELECT revision.* FROM %T revision + WHERE revision.ownerPHID in (%Ls) + AND revision.status IN (%Ld) + + UNION ALL + + SELECT revision.* FROM %T revision JOIN %T relationship + ON relationship.revisionID = revision.id + AND relationship.relation = %s + AND relationship.forbidden = 0 + WHERE relationship.objectPHID IN (%Ls) + AND revision.status in (%Ld) + + %Q', + $rev->getTableName(), + $this->ids, + array( + DifferentialRevisionStatus::NEEDS_REVIEW, + ), + $rev->getTableName(), + DifferentialRevision::RELATIONSHIP_TABLE, + DifferentialRevision::RELATION_REVIEWER, + $this->ids, + array( + DifferentialRevisionStatus::NEEDS_REVISION, + DifferentialRevisionStatus::ACCEPTED, + ), + $this->getOrderClause()); + + $data = ipull($data, null, 'id'); + + $this->revisions = $rev->loadAllFromArray($data); + break; + case self::QUERY_BY_PHID: + $this->revisions = $this->loadAllWhere( + 'revision.phid in (%Ls)', + $this->ids); + break; + } + + return $this->revisions; + } + + private function getOpenStatuses() { + return array( + DifferentialRevisionStatus::NEEDS_REVIEW, + DifferentialRevisionStatus::NEEDS_REVISION, + DifferentialRevisionStatus::ACCEPTED, + ); + } + + private function loadAllOpen() { + return $this->loadAllWhere('status in (%Ld)', $this->getOpenStatuses()); + } + + private function loadAllWhereJoinReview($pattern) { + $reviewer = DifferentialRevision::RELATION_REVIEWER; + + $argv = func_get_args(); + + $rev = new DifferentialRevision(); + + $pattern = array_shift($argv); + $pattern = + 'SELECT revision.* + FROM %T revision LEFT JOIN %T relationship + ON revision.id = relationship.revisionID + AND relationship.relation = %s + AND relationship.forbidden = 0 + WHERE '.$pattern.' + GROUP BY revision.id '.$this->getOrderClause(); + + array_unshift( + $argv, + $rev->getTableName(), + DifferentialRevision::RELATIONSHIP_TABLE, + DifferentialRevision::RELATION_REVIEWER); + + $data = vqueryfx_all( + $rev->establishConnection('r'), + $pattern, + $argv); + + return $rev->loadAllFromArray($data); + } + + private function loadAllWhere($pattern) { + $rev = new DifferentialRevision(); + + $argv = func_get_args(); + array_shift($argv); + array_unshift($argv, $rev->getTableName()); + + $data = vqueryfx_all( + $rev->establishConnection('r'), + 'SELECT * FROM %T revision WHERE '.$pattern, + $argv); + + return $rev->loadAllFromArray($data); + } + + private function loadAllOpenWithCCs(array $ccphids) { + $revision = new DifferentialRevision(); + $data = queryfx_all( + 'SELECT revision.* FROM %T revision + JOIN %T relationship ON relationship.revisionID = revision.id + AND relationship.relation = %s + AND relationship.forbidden = 0 + AND relationship.objectPHID in (%Ls) + WHERE revision.status in (%Ld) %Q', + $revision->getTableName(), + DifferentialRevision::RELATIONSHIP_TABLE, + DifferentialRevision::RELATION_SUBSCRIBED, + $ccphids, + $this->getOpenStatuses(), + $this->getOrderClause()); + return $revision->loadAllFromArray($data); + } + + private function getOrderClause() { + $reverse = false; + $order = $this->order; + + if (strlen($order) && $order[0] == '-') { + $reverse = true; + $order = substr($order, 1); + } + + $asc = $reverse ? 'DESC' : 'ASC'; + + switch ($order) { + case 'ID': + $clause = 'id'; + break; + case 'Revision': + $clause = 'name'; + break; + case 'Status': + $clause = 'status'; + break; + case 'Lines': + $clause = 'lineCount'; + break; + case 'Created': + $clause = 'dateCreated'; + $asc = $reverse ? 'ASC' : 'DESC'; + break; + case '': + case 'Modified': + $clause = 'dateModified'; + $asc = $reverse ? 'ASC' : 'DESC'; + break; + default: + throw new Exception("Invalid order '{$order}'."); + } + + return "ORDER BY {$clause} {$asc}"; + } + +} diff --git a/src/applications/differential/data/revisionlist/__init__.php b/src/applications/differential/data/revisionlist/__init__.php new file mode 100644 index 0000000000..166a7864cf --- /dev/null +++ b/src/applications/differential/data/revisionlist/__init__.php @@ -0,0 +1,16 @@ +path = $data['path']; $this->hash = $data['hash']; } public function processRequest() { $path = $this->path; // Sanity checking to keep this from exposing anything sensitive. $path = preg_replace('@(//|\\.\\.)@', '', $path); $matches = null; if (!preg_match('/\.(css|js)$/', $path, $matches)) { throw new Exception("Only CSS and JS resources may be served."); } $type = $matches[1]; $root = dirname(phutil_get_library_root('phabricator')); try { $data = Filesystem::readFile($root.'/webroot/'.$path); } catch (Exception $ex) { return new Aphront404Response(); } $response = new AphrontFileResponse(); $response->setContent($data); switch ($type) { case 'css': $response->setMimeType("text/css; charset=utf-8"); break; case 'js': $response->setMimeType("text/javascript; charset=utf-8"); break; } + + $response->setCacheDurationInSeconds(60 * 60 * 24 * 30); return $response; } } diff --git a/src/storage/queryfx/queryfx.php b/src/storage/queryfx/queryfx.php index 2a7d8d231f..32fa9c6d5d 100644 --- a/src/storage/queryfx/queryfx.php +++ b/src/storage/queryfx/queryfx.php @@ -1,58 +1,64 @@ executeRawQuery($query); } /** * @group storage */ function vqueryfx($conn, $sql, $argv) { array_unshift($argv, $conn, $sql); return call_user_func_array('queryfx', $argv); } /** * @group storage */ function queryfx_all($conn, $sql/*, ... */) { $argv = func_get_args(); $ret = call_user_func_array('queryfx', $argv); return $conn->selectAllResults($ret); } /** * @group storage */ function queryfx_one($conn, $sql/*, ... */) { $argv = func_get_args(); $ret = call_user_func_array('queryfx_all', $argv); if (count($ret) > 1) { throw new AphrontQueryCountException( 'Query returned more than one row.'); } else if (count($ret)) { return reset($ret); } return null; } + +function vqueryfx_all($conn, $sql, array $argv) { + array_unshift($argv, $conn, $sql); + $ret = call_user_func_array('queryfx', $argv); + return $conn->selectAllResults($ret); +} diff --git a/webroot/rsrc/css/aphront/side-nav-view.css b/webroot/rsrc/css/aphront/side-nav-view.css index 058fbe077f..4ace0af0ee 100644 --- a/webroot/rsrc/css/aphront/side-nav-view.css +++ b/webroot/rsrc/css/aphront/side-nav-view.css @@ -1,42 +1,43 @@ /** * @provides aphront-side-nav-view-css */ table.aphront-side-nav-view { width: 100%; + font-size: 13px; } td.aphront-side-nav-content { width: 100%; } th.aphront-side-nav-navigation { border-right: 1px solid #bbbbbb; } th.aphront-side-nav-navigation a { display: block; margin: 0 0 2px; min-width: 150px; padding: 3px 8px 3px 24px; font-weight: bold; white-space: nowrap; text-decoration: none; } th.aphront-side-nav-navigation a:hover { text-decoration: none; background: #f3f3f9; } th.aphront-side-nav-navigation hr { height: 1px; background: #eeeeee; border: 0px; margin: 12px 0px; } th.aphront-side-nav-navigation a.aphront-side-nav-selected, th.aphront-side-nav-navigation a.aphront-side-nav-selected:hover { background: #d8dfea; }