Page MenuHomePhorge

No OneTemporary

diff --git a/resources/sql/patches/045.timezone.sql b/resources/sql/patches/045.timezone.sql
new file mode 100644
index 0000000000..49c402b25b
--- /dev/null
+++ b/resources/sql/patches/045.timezone.sql
@@ -0,0 +1,2 @@
+ALTER TABLE phabricator_user.user
+ ADD timezoneIdentifier varchar(255) NOT NULL DEFAULT "America/Los_Angeles";
\ No newline at end of file
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index a9898fe78c..8e5a404477 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1,984 +1,987 @@
<?php
/**
* This file is automatically generated. Use 'phutil_mapper.php' to rebuild it.
* @generated
*/
phutil_register_library_map(array(
'class' =>
array(
'Aphront304Response' => 'aphront/response/304',
'Aphront400Response' => 'aphront/response/400',
'Aphront404Response' => 'aphront/response/404',
'AphrontAjaxResponse' => 'aphront/response/ajax',
'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration',
'AphrontAttachedFileView' => 'view/control/attachedfile',
'AphrontController' => 'aphront/controller',
'AphrontCrumbsView' => 'view/layout/crumbs',
'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',
'AphrontFilePreviewView' => 'view/layout/filepreview',
'AphrontFileResponse' => 'aphront/response/file',
'AphrontFormCheckboxControl' => 'view/form/control/checkbox',
'AphrontFormControl' => 'view/form/control/base',
'AphrontFormDividerControl' => 'view/form/control/divider',
'AphrontFormDragAndDropUploadControl' => 'view/form/control/draganddropupload',
'AphrontFormFileControl' => 'view/form/control/file',
'AphrontFormLayoutView' => 'view/form/layout',
'AphrontFormMarkupControl' => 'view/form/control/markup',
'AphrontFormPasswordControl' => 'view/form/control/password',
'AphrontFormRecaptchaControl' => 'view/form/control/recaptcha',
'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',
'AphrontFormToggleButtonsControl' => 'view/form/control/togglebuttons',
'AphrontFormTokenizerControl' => 'view/form/control/tokenizer',
'AphrontFormView' => 'view/form/base',
'AphrontHeadsupActionListView' => 'view/layout/headsup/actionlist',
'AphrontHeadsupActionView' => 'view/layout/headsup/action',
'AphrontIsolatedDatabaseConnection' => 'storage/connection/isolated',
'AphrontIsolatedDatabaseConnectionTestCase' => 'storage/connection/isolated/__tests__',
'AphrontKeyboardShortcutsAvailableView' => 'view/widget/keyboardshortcuts',
'AphrontListFilterView' => 'view/layout/listfilter',
'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql',
'AphrontNullView' => 'view/null',
'AphrontPageView' => 'view/page/base',
'AphrontPagerView' => 'view/control/pager',
'AphrontPanelView' => 'view/layout/panel',
'AphrontQueryAccessDeniedException' => 'storage/exception/accessdenied',
'AphrontQueryConnectionException' => 'storage/exception/connection',
'AphrontQueryConnectionLostException' => 'storage/exception/connectionlost',
'AphrontQueryCountException' => 'storage/exception/count',
'AphrontQueryDuplicateKeyException' => 'storage/exception/duplicatekey',
'AphrontQueryException' => 'storage/exception/base',
'AphrontQueryObjectMissingException' => 'storage/exception/objectmissing',
'AphrontQueryParameterException' => 'storage/exception/parameter',
'AphrontQueryRecoverableException' => 'storage/exception/recoverable',
'AphrontRedirectException' => 'aphront/exception/redirect',
'AphrontRedirectResponse' => 'aphront/response/redirect',
'AphrontReloadResponse' => 'aphront/response/reload',
'AphrontRequest' => 'aphront/request',
'AphrontRequestFailureView' => 'view/page/failure',
'AphrontResponse' => 'aphront/response/base',
'AphrontSideNavView' => 'view/layout/sidenav',
'AphrontTableView' => 'view/control/table',
'AphrontTokenizerTemplateView' => 'view/control/tokenizer',
'AphrontTypeaheadTemplateView' => 'view/control/typeahead',
'AphrontURIMapper' => 'aphront/mapper',
'AphrontView' => 'view/base',
'AphrontWebpageResponse' => 'aphront/response/webpage',
'CelerityAPI' => 'infrastructure/celerity/api',
'CelerityResourceController' => 'infrastructure/celerity/controller',
'CelerityResourceMap' => 'infrastructure/celerity/map',
'CelerityStaticResourceResponse' => 'infrastructure/celerity/response',
'ConduitAPIMethod' => 'applications/conduit/method/base',
'ConduitAPIRequest' => 'applications/conduit/protocol/request',
'ConduitAPI_conduit_connect_Method' => 'applications/conduit/method/conduit/connect',
'ConduitAPI_conduit_ping_Method' => 'applications/conduit/method/conduit/ping',
'ConduitAPI_daemon_launched_Method' => 'applications/conduit/method/daemon/launched',
'ConduitAPI_daemon_log_Method' => 'applications/conduit/method/daemon/log',
'ConduitAPI_differential_creatediff_Method' => 'applications/conduit/method/differential/creatediff',
'ConduitAPI_differential_createrevision_Method' => 'applications/conduit/method/differential/createrevision',
'ConduitAPI_differential_find_Method' => 'applications/conduit/method/differential/find',
'ConduitAPI_differential_getalldiffs_Method' => 'applications/conduit/method/differential/getalldiffs',
'ConduitAPI_differential_getcommitmessage_Method' => 'applications/conduit/method/differential/getcommitmessage',
'ConduitAPI_differential_getcommitpaths_Method' => 'applications/conduit/method/differential/getcommitpaths',
'ConduitAPI_differential_getdiff_Method' => 'applications/conduit/method/differential/getdiff',
'ConduitAPI_differential_getrevision_Method' => 'applications/conduit/method/differential/getrevision',
'ConduitAPI_differential_getrevisionfeedback_Method' => 'applications/conduit/method/differential/getrevisionfeedback',
'ConduitAPI_differential_markcommitted_Method' => 'applications/conduit/method/differential/markcommitted',
'ConduitAPI_differential_parsecommitmessage_Method' => 'applications/conduit/method/differential/parsecommitmessage',
'ConduitAPI_differential_setdiffproperty_Method' => 'applications/conduit/method/differential/setdiffproperty',
'ConduitAPI_differential_updaterevision_Method' => 'applications/conduit/method/differential/updaterevision',
'ConduitAPI_differential_updatetaskrevisionassoc_Method' => 'applications/conduit/method/differential/updatetaskrevisionassoc',
'ConduitAPI_differential_updateunitresults_Method' => 'applications/conduit/method/differential/updateunitresults',
'ConduitAPI_diffusion_getcommits_Method' => 'applications/conduit/method/diffusion/getcommits',
'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'applications/conduit/method/diffusion/getrecentcommitsbypath',
'ConduitAPI_file_download_Method' => 'applications/conduit/method/file/download',
'ConduitAPI_file_upload_Method' => 'applications/conduit/method/file/upload',
'ConduitAPI_paste_info_Method' => 'applications/conduit/method/paste/info',
'ConduitAPI_path_getowners_Method' => 'applications/conduit/method/path/getowners',
'ConduitAPI_user_find_Method' => 'applications/conduit/method/user/find',
'ConduitAPI_user_whoami_Method' => 'applications/conduit/method/user/whoami',
'ConduitException' => 'applications/conduit/protocol/exception',
'DarkConsole' => 'aphront/console/api',
'DarkConsoleConfigPlugin' => 'aphront/console/plugin/config',
'DarkConsoleController' => 'aphront/console/controller',
'DarkConsoleCore' => 'aphront/console/core',
'DarkConsoleErrorLogPlugin' => 'aphront/console/plugin/errorlog',
'DarkConsoleErrorLogPluginAPI' => 'aphront/console/plugin/errorlog/api',
'DarkConsolePlugin' => 'aphront/console/plugin/base',
'DarkConsoleRequestPlugin' => 'aphront/console/plugin/request',
'DarkConsoleServicesPlugin' => 'aphront/console/plugin/services',
'DarkConsoleXHProfPlugin' => 'aphront/console/plugin/xhprof',
'DarkConsoleXHProfPluginAPI' => 'aphront/console/plugin/xhprof/api',
'DatabaseConfigurationProvider' => 'applications/base/storage/configuration',
'DifferentialAction' => 'applications/differential/constants/action',
'DifferentialAddCommentView' => 'applications/differential/view/addcomment',
'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',
'DifferentialComment' => 'applications/differential/storage/comment',
'DifferentialCommentEditor' => 'applications/differential/editor/comment',
'DifferentialCommentMail' => 'applications/differential/mail/comment',
'DifferentialCommentPreviewController' => 'applications/differential/controller/commentpreview',
'DifferentialCommentSaveController' => 'applications/differential/controller/commentsave',
'DifferentialCommitMessage' => 'applications/differential/parser/commitmessage',
'DifferentialCommitMessageData' => 'applications/differential/data/commitmessage',
'DifferentialCommitMessageParserException' => 'applications/differential/parser/commitmessage/exception',
'DifferentialController' => 'applications/differential/controller/base',
'DifferentialDAO' => 'applications/differential/storage/base',
'DifferentialDiff' => 'applications/differential/storage/diff',
'DifferentialDiffContentMail' => 'applications/differential/mail/diffcontent',
'DifferentialDiffCreateController' => 'applications/differential/controller/diffcreate',
'DifferentialDiffProperty' => 'applications/differential/storage/diffproperty',
'DifferentialDiffTableOfContentsView' => 'applications/differential/view/difftableofcontents',
'DifferentialDiffViewController' => 'applications/differential/controller/diffview',
'DifferentialExceptionMail' => 'applications/differential/mail/exception',
'DifferentialHunk' => 'applications/differential/storage/hunk',
'DifferentialInlineComment' => 'applications/differential/storage/inlinecomment',
'DifferentialInlineCommentEditController' => 'applications/differential/controller/inlinecommentedit',
'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/inlinecommentpreview',
'DifferentialInlineCommentView' => 'applications/differential/view/inlinecomment',
'DifferentialLintStatus' => 'applications/differential/constants/lintstatus',
'DifferentialMail' => 'applications/differential/mail/base',
'DifferentialMarkupEngineFactory' => 'applications/differential/parser/markup',
'DifferentialNewDiffMail' => 'applications/differential/mail/newdiff',
'DifferentialPrimaryPaneView' => 'applications/differential/view/primarypane',
'DifferentialReplyHandler' => 'applications/differential/replyhandler',
'DifferentialReviewRequestMail' => 'applications/differential/mail/reviewrequest',
'DifferentialRevision' => 'applications/differential/storage/revision',
'DifferentialRevisionCommentListView' => 'applications/differential/view/revisioncommentlist',
'DifferentialRevisionCommentView' => 'applications/differential/view/revisioncomment',
'DifferentialRevisionControlSystem' => 'applications/differential/constants/revisioncontrolsystem',
'DifferentialRevisionDetailRenderer' => 'applications/differential/controller/customrenderer',
'DifferentialRevisionDetailView' => 'applications/differential/view/revisiondetail',
'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',
'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/revisionupdatehistory',
'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview',
'DifferentialSubscribeController' => 'applications/differential/controller/subscribe',
'DifferentialTasksAttacher' => 'applications/differential/tasks',
'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus',
'DifferentialUnitTestResult' => 'applications/differential/constants/unittestresult',
'DifferentialViewTime' => 'applications/differential/storage/viewtime',
'DiffusionBranchInformation' => 'applications/diffusion/data/branch',
'DiffusionBranchQuery' => 'applications/diffusion/query/branch/base',
'DiffusionBranchTableView' => 'applications/diffusion/view/branchtable',
'DiffusionBrowseController' => 'applications/diffusion/controller/browse',
'DiffusionBrowseFileController' => 'applications/diffusion/controller/file',
'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/base',
'DiffusionBrowseTableView' => 'applications/diffusion/view/browsetable',
'DiffusionChangeController' => 'applications/diffusion/controller/change',
'DiffusionCommitChangeTableView' => 'applications/diffusion/view/commitchangetable',
'DiffusionCommitController' => 'applications/diffusion/controller/commit',
'DiffusionController' => 'applications/diffusion/controller/base',
'DiffusionDiffController' => 'applications/diffusion/controller/diff',
'DiffusionDiffQuery' => 'applications/diffusion/query/diff/base',
'DiffusionFileContent' => 'applications/diffusion/data/filecontent',
'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/base',
'DiffusionGitBranchQuery' => 'applications/diffusion/query/branch/git',
'DiffusionGitBrowseQuery' => 'applications/diffusion/query/browse/git',
'DiffusionGitDiffQuery' => 'applications/diffusion/query/diff/git',
'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/git',
'DiffusionGitHistoryQuery' => 'applications/diffusion/query/history/git',
'DiffusionGitLastModifiedQuery' => 'applications/diffusion/query/lastmodified/git',
'DiffusionGitPathIDQuery' => 'applications/diffusion/query/pathid/base',
'DiffusionGitRequest' => 'applications/diffusion/request/git',
'DiffusionHistoryController' => 'applications/diffusion/controller/history',
'DiffusionHistoryQuery' => 'applications/diffusion/query/history/base',
'DiffusionHistoryTableView' => 'applications/diffusion/view/historytable',
'DiffusionHomeController' => 'applications/diffusion/controller/home',
'DiffusionLastModifiedController' => 'applications/diffusion/controller/lastmodified',
'DiffusionLastModifiedQuery' => 'applications/diffusion/query/lastmodified/base',
'DiffusionPathChange' => 'applications/diffusion/data/pathchange',
'DiffusionPathChangeQuery' => 'applications/diffusion/query/pathchange/base',
'DiffusionPathCompleteController' => 'applications/diffusion/controller/pathcomplete',
'DiffusionPathValidateController' => 'applications/diffusion/controller/pathvalidate',
'DiffusionRepositoryController' => 'applications/diffusion/controller/repository',
'DiffusionRepositoryPath' => 'applications/diffusion/data/repositorypath',
'DiffusionRequest' => 'applications/diffusion/request/base',
'DiffusionSvnBrowseQuery' => 'applications/diffusion/query/browse/svn',
'DiffusionSvnDiffQuery' => 'applications/diffusion/query/diff/svn',
'DiffusionSvnFileContentQuery' => 'applications/diffusion/query/filecontent/svn',
'DiffusionSvnHistoryQuery' => 'applications/diffusion/query/history/svn',
'DiffusionSvnLastModifiedQuery' => 'applications/diffusion/query/lastmodified/svn',
'DiffusionSvnRequest' => 'applications/diffusion/request/svn',
'DiffusionView' => 'applications/diffusion/view/base',
'HeraldAction' => 'applications/herald/storage/action',
'HeraldActionConfig' => 'applications/herald/config/action',
'HeraldApplyTranscript' => 'applications/herald/storage/transcript/apply',
'HeraldCommitAdapter' => 'applications/herald/adapter/commit',
'HeraldCondition' => 'applications/herald/storage/condition',
'HeraldConditionConfig' => 'applications/herald/config/condition',
'HeraldConditionTranscript' => 'applications/herald/storage/transcript/condition',
'HeraldContentTypeConfig' => 'applications/herald/config/contenttype',
'HeraldController' => 'applications/herald/controller/base',
'HeraldDAO' => 'applications/herald/storage/base',
'HeraldDeleteController' => 'applications/herald/controller/delete',
'HeraldDifferentialRevisionAdapter' => 'applications/herald/adapter/differential',
'HeraldDryRunAdapter' => 'applications/herald/adapter/dryrun',
'HeraldEffect' => 'applications/herald/engine/effect',
'HeraldEngine' => 'applications/herald/engine/engine',
'HeraldFieldConfig' => 'applications/herald/config/field',
'HeraldHomeController' => 'applications/herald/controller/home',
'HeraldInvalidConditionException' => 'applications/herald/engine/engine/exception',
'HeraldInvalidFieldException' => 'applications/herald/engine/engine/exception',
'HeraldNewController' => 'applications/herald/controller/new',
'HeraldObjectAdapter' => 'applications/herald/adapter/base',
'HeraldObjectTranscript' => 'applications/herald/storage/transcript/object',
'HeraldRecursiveConditionsException' => 'applications/herald/engine/engine/exception',
'HeraldRepetitionPolicyConfig' => 'applications/herald/config/repetitionpolicy',
'HeraldRule' => 'applications/herald/storage/rule',
'HeraldRuleController' => 'applications/herald/controller/rule',
'HeraldRuleTranscript' => 'applications/herald/storage/transcript/rule',
'HeraldTestConsoleController' => 'applications/herald/controller/test',
'HeraldTranscript' => 'applications/herald/storage/transcript/base',
'HeraldTranscriptController' => 'applications/herald/controller/transcript',
'HeraldTranscriptListController' => 'applications/herald/controller/transcriptlist',
'HeraldValueTypeConfig' => 'applications/herald/config/valuetype',
'Javelin' => 'infrastructure/javelin/api',
'LiskDAO' => 'storage/lisk/dao',
'LiskIsolationTestCase' => 'storage/lisk/dao/__tests__',
'LiskIsolationTestDAO' => 'storage/lisk/dao/__tests__',
'LiskIsolationTestDAOException' => 'storage/lisk/dao/__tests__',
'ManiphestController' => 'applications/maniphest/controller/base',
'ManiphestDAO' => 'applications/maniphest/storage/base',
'ManiphestReplyHandler' => 'applications/maniphest/replyhandler',
'ManiphestTask' => 'applications/maniphest/storage/task',
'ManiphestTaskDescriptionChangeController' => 'applications/maniphest/controller/descriptionchange',
'ManiphestTaskDetailController' => 'applications/maniphest/controller/taskdetail',
'ManiphestTaskEditController' => 'applications/maniphest/controller/taskedit',
'ManiphestTaskListController' => 'applications/maniphest/controller/tasklist',
'ManiphestTaskListView' => 'applications/maniphest/view/tasklist',
'ManiphestTaskPriority' => 'applications/maniphest/constants/priority',
'ManiphestTaskStatus' => 'applications/maniphest/constants/status',
'ManiphestTaskSummaryView' => 'applications/maniphest/view/tasksummary',
'ManiphestTransaction' => 'applications/maniphest/storage/transaction',
'ManiphestTransactionDetailView' => 'applications/maniphest/view/transactiondetail',
'ManiphestTransactionEditor' => 'applications/maniphest/editor/transaction',
'ManiphestTransactionListView' => 'applications/maniphest/view/transactionlist',
'ManiphestTransactionPreviewController' => 'applications/maniphest/controller/transactionpreview',
'ManiphestTransactionSaveController' => 'applications/maniphest/controller/transactionsave',
'ManiphestTransactionType' => 'applications/maniphest/constants/transactiontype',
'Phabricator404Controller' => 'applications/base/controller/404',
'PhabricatorAuthController' => 'applications/auth/controller/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',
'PhabricatorCountdownController' => 'applications/countdown/controller/base',
'PhabricatorCountdownDAO' => 'applications/countdown/storage/base',
'PhabricatorCountdownDeleteController' => 'applications/countdown/controller/delete',
'PhabricatorCountdownEditController' => 'applications/countdown/controller/edit',
'PhabricatorCountdownListController' => 'applications/countdown/controller/list',
'PhabricatorCountdownViewController' => 'applications/countdown/controller/view',
'PhabricatorDaemon' => 'infrastructure/daemon/base',
'PhabricatorDaemonCombinedLogController' => 'applications/daemon/controller/combined',
'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/console',
'PhabricatorDaemonControl' => 'infrastructure/daemon/control',
'PhabricatorDaemonController' => 'applications/daemon/controller/base',
'PhabricatorDaemonDAO' => 'infrastructure/daemon/storage/base',
'PhabricatorDaemonLog' => 'infrastructure/daemon/storage/log',
'PhabricatorDaemonLogEvent' => 'infrastructure/daemon/storage/event',
'PhabricatorDaemonLogEventsView' => 'applications/daemon/view/daemonlogevents',
'PhabricatorDaemonLogListController' => 'applications/daemon/controller/loglist',
'PhabricatorDaemonLogListView' => 'applications/daemon/view/daemonloglist',
'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/logview',
'PhabricatorDaemonReference' => 'infrastructure/daemon/control/reference',
'PhabricatorDaemonTimelineConsoleController' => 'applications/daemon/controller/timeline',
'PhabricatorDaemonTimelineEventController' => 'applications/daemon/controller/timelineevent',
'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',
'PhabricatorDisabledUserController' => 'applications/auth/controller/disabled',
'PhabricatorDraft' => 'applications/draft/storage/draft',
'PhabricatorDraftDAO' => 'applications/draft/storage/base',
'PhabricatorEditPreferencesController' => 'applications/preferences/controller/edit',
'PhabricatorEmailLoginController' => 'applications/auth/controller/email',
'PhabricatorEmailTokenController' => 'applications/auth/controller/emailtoken',
'PhabricatorEnv' => 'infrastructure/env',
'PhabricatorFile' => 'applications/files/storage/file',
'PhabricatorFileController' => 'applications/files/controller/base',
'PhabricatorFileDAO' => 'applications/files/storage/base',
'PhabricatorFileDropUploadController' => 'applications/files/controller/dropupload',
'PhabricatorFileImageMacro' => 'applications/files/storage/imagemacro',
'PhabricatorFileListController' => 'applications/files/controller/list',
'PhabricatorFileMacroDeleteController' => 'applications/files/controller/macrodelete',
'PhabricatorFileMacroEditController' => 'applications/files/controller/macroedit',
'PhabricatorFileMacroListController' => 'applications/files/controller/macrolist',
'PhabricatorFileProxyController' => 'applications/files/controller/proxy',
'PhabricatorFileProxyImage' => 'applications/files/storage/proxyimage',
'PhabricatorFileStorageBlob' => 'applications/files/storage/storageblob',
'PhabricatorFileTransformController' => 'applications/files/controller/transform',
'PhabricatorFileURI' => 'applications/files/uri',
'PhabricatorFileUploadController' => 'applications/files/controller/upload',
'PhabricatorFileViewController' => 'applications/files/controller/view',
'PhabricatorGoodForNothingWorker' => 'infrastructure/daemon/workers/worker/goodfornothing',
'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/selector',
'PhabricatorHelpController' => 'applications/help/controller/base',
'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/keyboardshortcut',
'PhabricatorIRCBot' => 'infrastructure/daemon/irc/bot',
'PhabricatorIRCHandler' => 'infrastructure/daemon/irc/handler/base',
'PhabricatorIRCMessage' => 'infrastructure/daemon/irc/message',
'PhabricatorIRCObjectNameHandler' => 'infrastructure/daemon/irc/handler/objectname',
'PhabricatorIRCProtocolHandler' => 'infrastructure/daemon/irc/handler/protocol',
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/javelin',
'PhabricatorLintEngine' => 'infrastructure/lint/engine',
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
'PhabricatorLoginController' => 'applications/auth/controller/login',
'PhabricatorLogoutController' => 'applications/auth/controller/logout',
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/base',
'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/amazonses',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/phpmailerlite',
'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/sendgrid',
'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/test',
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/base',
'PhabricatorMetaMTAController' => 'applications/metamta/controller/base',
'PhabricatorMetaMTADAO' => 'applications/metamta/storage/base',
'PhabricatorMetaMTADaemon' => 'applications/metamta/daemon/mta',
'PhabricatorMetaMTAEmailBodyParser' => 'applications/metamta/parser',
'PhabricatorMetaMTAEmailBodyParserTestCase' => 'applications/metamta/parser/__tests__',
'PhabricatorMetaMTAListController' => 'applications/metamta/controller/list',
'PhabricatorMetaMTAMail' => 'applications/metamta/storage/mail',
'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/mail/__tests__',
'PhabricatorMetaMTAMailingList' => 'applications/metamta/storage/mailinglist',
'PhabricatorMetaMTAMailingListEditController' => 'applications/metamta/controller/mailinglistedit',
'PhabricatorMetaMTAMailingListsController' => 'applications/metamta/controller/mailinglists',
'PhabricatorMetaMTAReceiveController' => 'applications/metamta/controller/receive',
'PhabricatorMetaMTAReceivedListController' => 'applications/metamta/controller/receivedlist',
'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/receivedmail',
'PhabricatorMetaMTASendController' => 'applications/metamta/controller/send',
'PhabricatorMetaMTASendGridReceiveController' => 'applications/metamta/controller/sendgridreceive',
'PhabricatorMetaMTAViewController' => 'applications/metamta/controller/view',
'PhabricatorOAuthDefaultRegistrationController' => 'applications/auth/controller/oauthregistration/default',
'PhabricatorOAuthDiagnosticsController' => 'applications/auth/controller/oauthdiagnostics',
'PhabricatorOAuthFailureView' => 'applications/auth/view/oauthfailure',
'PhabricatorOAuthLoginController' => 'applications/auth/controller/oauth',
'PhabricatorOAuthProvider' => 'applications/auth/oauth/provider/base',
'PhabricatorOAuthProviderFacebook' => 'applications/auth/oauth/provider/facebook',
'PhabricatorOAuthProviderGithub' => 'applications/auth/oauth/provider/github',
'PhabricatorOAuthRegistrationController' => 'applications/auth/controller/oauthregistration/base',
'PhabricatorOAuthUnlinkController' => 'applications/auth/controller/unlink',
'PhabricatorObjectHandle' => 'applications/phid/handle',
'PhabricatorObjectHandleData' => 'applications/phid/handle/data',
'PhabricatorObjectSelectorDialog' => 'view/control/objectselector',
'PhabricatorOwnersController' => 'applications/owners/controller/base',
'PhabricatorOwnersDAO' => 'applications/owners/storage/base',
'PhabricatorOwnersDeleteController' => 'applications/owners/controller/delete',
'PhabricatorOwnersDetailController' => 'applications/owners/controller/detail',
'PhabricatorOwnersEditController' => 'applications/owners/controller/edit',
'PhabricatorOwnersListController' => 'applications/owners/controller/list',
'PhabricatorOwnersOwner' => 'applications/owners/storage/owner',
'PhabricatorOwnersPackage' => 'applications/owners/storage/package',
'PhabricatorOwnersPath' => 'applications/owners/storage/path',
'PhabricatorPHID' => 'applications/phid/storage/phid',
'PhabricatorPHIDAllocateController' => 'applications/phid/controller/allocate',
'PhabricatorPHIDConstants' => 'applications/phid/constants',
'PhabricatorPHIDController' => 'applications/phid/controller/base',
'PhabricatorPHIDDAO' => 'applications/phid/storage/base',
'PhabricatorPHIDListController' => 'applications/phid/controller/list',
'PhabricatorPHIDLookupController' => 'applications/phid/controller/lookup',
'PhabricatorPaste' => 'applications/paste/storage/paste',
'PhabricatorPasteController' => 'applications/paste/controller/base',
'PhabricatorPasteCreateController' => 'applications/paste/controller/create',
'PhabricatorPasteDAO' => 'applications/paste/storage/base',
'PhabricatorPasteListController' => 'applications/paste/controller/list',
'PhabricatorPasteViewController' => 'applications/paste/controller/view',
'PhabricatorPeopleController' => 'applications/people/controller/base',
'PhabricatorPeopleEditController' => 'applications/people/controller/edit',
'PhabricatorPeopleListController' => 'applications/people/controller/list',
'PhabricatorPeopleLogsController' => 'applications/people/controller/logs',
'PhabricatorPeopleProfileController' => 'applications/people/controller/profile',
'PhabricatorPeopleProfileEditController' => 'applications/people/controller/profileedit',
'PhabricatorPreferencesController' => 'applications/preferences/controller/base',
'PhabricatorProject' => 'applications/project/storage/project',
'PhabricatorProjectAffiliation' => 'applications/project/storage/affiliation',
'PhabricatorProjectAffiliationEditController' => 'applications/project/controller/editaffiliation',
'PhabricatorProjectController' => 'applications/project/controller/base',
'PhabricatorProjectDAO' => 'applications/project/storage/base',
'PhabricatorProjectEditController' => 'applications/project/controller/edit',
'PhabricatorProjectListController' => 'applications/project/controller/list',
'PhabricatorProjectProfile' => 'applications/project/storage/profile',
'PhabricatorProjectProfileController' => 'applications/project/controller/profile',
'PhabricatorProjectQuickCreateController' => 'applications/project/controller/quickcreate',
'PhabricatorRedirectController' => 'applications/base/controller/redirect',
'PhabricatorRemarkupRuleDifferential' => 'infrastructure/markup/remarkup/markuprule/differential',
'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/remarkup/markuprule/diffusion',
'PhabricatorRemarkupRuleImageMacro' => 'infrastructure/markup/remarkup/markuprule/imagemacro',
'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/remarkup/markuprule/maniphest',
'PhabricatorRemarkupRuleObjectName' => 'infrastructure/markup/remarkup/markuprule/objectname',
'PhabricatorRemarkupRuleProxyImage' => 'infrastructure/markup/remarkup/markuprule/proxyimage',
'PhabricatorRemarkupRuleYoutube' => 'infrastructure/markup/remarkup/markuprule/youtube',
'PhabricatorRepository' => 'applications/repository/storage/repository',
'PhabricatorRepositoryArcanistProject' => 'applications/repository/storage/arcanistproject',
'PhabricatorRepositoryArcanistProjectEditController' => 'applications/repository/controller/arcansistprojectedit',
'PhabricatorRepositoryCommit' => 'applications/repository/storage/commit',
'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/base',
'PhabricatorRepositoryCommitData' => 'applications/repository/storage/commitdata',
'PhabricatorRepositoryCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/base',
'PhabricatorRepositoryCommitHeraldWorker' => 'applications/repository/worker/herald',
'PhabricatorRepositoryCommitMessageDetailParser' => 'applications/repository/parser/base',
'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/base',
'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/base',
'PhabricatorRepositoryCommitTaskDaemon' => 'applications/repository/daemon/committask',
'PhabricatorRepositoryController' => 'applications/repository/controller/base',
'PhabricatorRepositoryCreateController' => 'applications/repository/controller/create',
'PhabricatorRepositoryDAO' => 'applications/repository/storage/base',
'PhabricatorRepositoryDaemon' => 'applications/repository/daemon/base',
'PhabricatorRepositoryDefaultCommitMessageDetailParser' => 'applications/repository/parser/default',
'PhabricatorRepositoryDeleteController' => 'applications/repository/controller/delete',
'PhabricatorRepositoryEditController' => 'applications/repository/controller/edit',
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/git',
'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/git',
'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/git',
'PhabricatorRepositoryGitFetchDaemon' => 'applications/repository/daemon/gitfetch',
'PhabricatorRepositoryGitHubNotification' => 'applications/repository/storage/githubnotification',
'PhabricatorRepositoryGitHubPostReceiveController' => 'applications/repository/controller/github-post-receive',
'PhabricatorRepositoryListController' => 'applications/repository/controller/list',
'PhabricatorRepositoryShortcut' => 'applications/repository/storage/shortcut',
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/svn',
'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/svn',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/svn',
'PhabricatorRepositoryType' => 'applications/repository/constants/repositorytype',
'PhabricatorSQLPatchList' => 'infrastructure/setup/sql',
'PhabricatorSearchAbstractDocument' => 'applications/search/index/abstractdocument',
'PhabricatorSearchAttachController' => 'applications/search/controller/attach',
'PhabricatorSearchBaseController' => 'applications/search/controller/base',
'PhabricatorSearchController' => 'applications/search/controller/search',
'PhabricatorSearchDAO' => 'applications/search/storage/base',
'PhabricatorSearchDifferentialIndexer' => 'applications/search/index/indexer/differential',
'PhabricatorSearchDocument' => 'applications/search/storage/document/document',
'PhabricatorSearchDocumentField' => 'applications/search/storage/document/field',
'PhabricatorSearchDocumentIndexer' => 'applications/search/index/indexer/base',
'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/relationship',
'PhabricatorSearchExecutor' => 'applications/search/execute/base',
'PhabricatorSearchField' => 'applications/search/constants/field',
'PhabricatorSearchManiphestIndexer' => 'applications/search/index/indexer/maniphest',
'PhabricatorSearchMySQLExecutor' => 'applications/search/execute/mysql',
'PhabricatorSearchQuery' => 'applications/search/storage/query',
'PhabricatorSearchRelationship' => 'applications/search/constants/relationship',
'PhabricatorSearchSelectController' => 'applications/search/controller/select',
'PhabricatorSetup' => 'infrastructure/setup',
'PhabricatorStandardPageView' => 'view/page/standard',
'PhabricatorStatusController' => 'applications/status/base',
'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/taskmaster',
'PhabricatorTestCase' => 'infrastructure/testing/testcase',
'PhabricatorTimelineCursor' => 'infrastructure/daemon/timeline/storage/cursor',
'PhabricatorTimelineDAO' => 'infrastructure/daemon/timeline/storage/base',
'PhabricatorTimelineEvent' => 'infrastructure/daemon/timeline/storage/event',
'PhabricatorTimelineEventData' => 'infrastructure/daemon/timeline/storage/eventdata',
'PhabricatorTimelineIterator' => 'infrastructure/daemon/timeline/cursor/iterator',
'PhabricatorTimer' => 'applications/countdown/storage/timer',
'PhabricatorTransformedFile' => 'applications/files/storage/transformed',
'PhabricatorTypeaheadCommonDatasourceController' => 'applications/typeahead/controller/common',
'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/base',
'PhabricatorUIExample' => 'applications/uiexample/examples/base',
'PhabricatorUIExampleController' => 'applications/uiexample/controller/base',
'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/render',
'PhabricatorUIListFilterExample' => 'applications/uiexample/examples/listfilter',
'PhabricatorUIPagerExample' => 'applications/uiexample/examples/pager',
'PhabricatorUser' => 'applications/people/storage/user',
'PhabricatorUserDAO' => 'applications/people/storage/base',
'PhabricatorUserLog' => 'applications/people/storage/log',
'PhabricatorUserOAuthInfo' => 'applications/people/storage/useroauthinfo',
'PhabricatorUserPreferences' => 'applications/people/storage/preferences',
'PhabricatorUserProfile' => 'applications/people/storage/profile',
'PhabricatorUserSettingsController' => 'applications/people/controller/settings',
'PhabricatorWorker' => 'infrastructure/daemon/workers/worker',
'PhabricatorWorkerDAO' => 'infrastructure/daemon/workers/storage/base',
'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/task',
'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/taskdata',
'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/workertaskdetail',
'PhabricatorXHPASTViewController' => 'applications/xhpastview/controller/base',
'PhabricatorXHPASTViewDAO' => 'applications/xhpastview/storage/base',
'PhabricatorXHPASTViewFrameController' => 'applications/xhpastview/controller/viewframe',
'PhabricatorXHPASTViewFramesetController' => 'applications/xhpastview/controller/viewframeset',
'PhabricatorXHPASTViewInputController' => 'applications/xhpastview/controller/viewinput',
'PhabricatorXHPASTViewPanelController' => 'applications/xhpastview/controller/viewpanel',
'PhabricatorXHPASTViewParseTree' => 'applications/xhpastview/storage/parsetree',
'PhabricatorXHPASTViewRunController' => 'applications/xhpastview/controller/run',
'PhabricatorXHPASTViewStreamController' => 'applications/xhpastview/controller/viewstream',
'PhabricatorXHPASTViewTreeController' => 'applications/xhpastview/controller/viewtree',
'PhabricatorXHProfController' => 'applications/xhprof/controller/base',
'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/profile',
'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol',
'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel',
),
'function' =>
array(
'_qsprintf_check_scalar_type' => 'storage/qsprintf',
'_qsprintf_check_type' => 'storage/qsprintf',
'celerity_generate_unique_node_id' => 'infrastructure/celerity/api',
'celerity_register_resource_map' => 'infrastructure/celerity/map',
'javelin_render_tag' => 'infrastructure/javelin/markup',
+ 'phabricator_date' => 'view/utils',
+ 'phabricator_datetime' => 'view/utils',
'phabricator_format_relative_time' => 'view/utils',
'phabricator_format_timestamp' => 'view/utils',
'phabricator_format_units_generic' => 'view/utils',
'phabricator_render_form' => 'infrastructure/javelin/markup',
+ 'phabricator_time' => 'view/utils',
'qsprintf' => 'storage/qsprintf',
'queryfx' => 'storage/queryfx',
'queryfx_all' => 'storage/queryfx',
'queryfx_one' => 'storage/queryfx',
'require_celerity_resource' => 'infrastructure/celerity/api',
'vqsprintf' => 'storage/qsprintf',
'vqueryfx' => 'storage/queryfx',
'vqueryfx_all' => 'storage/queryfx',
'xsprintf_query' => 'storage/qsprintf',
),
'requires_class' =>
array(
'Aphront304Response' => 'AphrontResponse',
'Aphront400Response' => 'AphrontResponse',
'Aphront404Response' => 'AphrontResponse',
'AphrontAjaxResponse' => 'AphrontResponse',
'AphrontAttachedFileView' => 'AphrontView',
'AphrontCrumbsView' => 'AphrontView',
'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration',
'AphrontDefaultApplicationController' => 'AphrontController',
'AphrontDialogResponse' => 'AphrontResponse',
'AphrontDialogView' => 'AphrontView',
'AphrontErrorView' => 'AphrontView',
'AphrontFilePreviewView' => 'AphrontView',
'AphrontFileResponse' => 'AphrontResponse',
'AphrontFormCheckboxControl' => 'AphrontFormControl',
'AphrontFormControl' => 'AphrontView',
'AphrontFormDividerControl' => 'AphrontFormControl',
'AphrontFormDragAndDropUploadControl' => 'AphrontFormControl',
'AphrontFormFileControl' => 'AphrontFormControl',
'AphrontFormLayoutView' => 'AphrontView',
'AphrontFormMarkupControl' => 'AphrontFormControl',
'AphrontFormPasswordControl' => 'AphrontFormControl',
'AphrontFormRecaptchaControl' => 'AphrontFormControl',
'AphrontFormSelectControl' => 'AphrontFormControl',
'AphrontFormStaticControl' => 'AphrontFormControl',
'AphrontFormSubmitControl' => 'AphrontFormControl',
'AphrontFormTextAreaControl' => 'AphrontFormControl',
'AphrontFormTextControl' => 'AphrontFormControl',
'AphrontFormToggleButtonsControl' => 'AphrontFormControl',
'AphrontFormTokenizerControl' => 'AphrontFormControl',
'AphrontFormView' => 'AphrontView',
'AphrontHeadsupActionListView' => 'AphrontView',
'AphrontHeadsupActionView' => 'AphrontView',
'AphrontIsolatedDatabaseConnection' => 'AphrontDatabaseConnection',
'AphrontIsolatedDatabaseConnectionTestCase' => 'PhabricatorTestCase',
'AphrontKeyboardShortcutsAvailableView' => 'AphrontView',
'AphrontListFilterView' => 'AphrontView',
'AphrontMySQLDatabaseConnection' => 'AphrontDatabaseConnection',
'AphrontNullView' => 'AphrontView',
'AphrontPageView' => 'AphrontView',
'AphrontPagerView' => 'AphrontView',
'AphrontPanelView' => 'AphrontView',
'AphrontQueryAccessDeniedException' => 'AphrontQueryRecoverableException',
'AphrontQueryConnectionException' => 'AphrontQueryException',
'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException',
'AphrontQueryCountException' => 'AphrontQueryException',
'AphrontQueryDuplicateKeyException' => 'AphrontQueryException',
'AphrontQueryObjectMissingException' => 'AphrontQueryException',
'AphrontQueryParameterException' => 'AphrontQueryException',
'AphrontQueryRecoverableException' => 'AphrontQueryException',
'AphrontRedirectException' => 'AphrontException',
'AphrontRedirectResponse' => 'AphrontResponse',
'AphrontReloadResponse' => 'AphrontRedirectResponse',
'AphrontRequestFailureView' => 'AphrontView',
'AphrontSideNavView' => 'AphrontView',
'AphrontTableView' => 'AphrontView',
'AphrontTokenizerTemplateView' => 'AphrontView',
'AphrontTypeaheadTemplateView' => 'AphrontView',
'AphrontWebpageResponse' => 'AphrontResponse',
'CelerityResourceController' => 'AphrontController',
'ConduitAPI_conduit_connect_Method' => 'ConduitAPIMethod',
'ConduitAPI_conduit_ping_Method' => 'ConduitAPIMethod',
'ConduitAPI_daemon_launched_Method' => 'ConduitAPIMethod',
'ConduitAPI_daemon_log_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_creatediff_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_createrevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_find_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getalldiffs_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getcommitmessage_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getcommitpaths_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getdiff_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getrevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_getrevisionfeedback_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_markcommitted_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_parsecommitmessage_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_updaterevision_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_updatetaskrevisionassoc_Method' => 'ConduitAPIMethod',
'ConduitAPI_differential_updateunitresults_Method' => 'ConduitAPIMethod',
'ConduitAPI_diffusion_getcommits_Method' => 'ConduitAPIMethod',
'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'ConduitAPIMethod',
'ConduitAPI_file_download_Method' => 'ConduitAPIMethod',
'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod',
'ConduitAPI_paste_info_Method' => 'ConduitAPIMethod',
'ConduitAPI_path_getowners_Method' => 'ConduitAPIMethod',
'ConduitAPI_user_find_Method' => 'ConduitAPIMethod',
'ConduitAPI_user_whoami_Method' => 'ConduitAPIMethod',
'DarkConsoleConfigPlugin' => 'DarkConsolePlugin',
'DarkConsoleController' => 'PhabricatorController',
'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin',
'DarkConsoleRequestPlugin' => 'DarkConsolePlugin',
'DarkConsoleServicesPlugin' => 'DarkConsolePlugin',
'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin',
'DifferentialAddCommentView' => 'AphrontView',
'DifferentialCCWelcomeMail' => 'DifferentialReviewRequestMail',
'DifferentialChangeset' => 'DifferentialDAO',
'DifferentialChangesetDetailView' => 'AphrontView',
'DifferentialChangesetListView' => 'AphrontView',
'DifferentialChangesetViewController' => 'DifferentialController',
'DifferentialComment' => 'DifferentialDAO',
'DifferentialCommentMail' => 'DifferentialMail',
'DifferentialCommentPreviewController' => 'DifferentialController',
'DifferentialCommentSaveController' => 'DifferentialController',
'DifferentialController' => 'PhabricatorController',
'DifferentialDAO' => 'PhabricatorLiskDAO',
'DifferentialDiff' => 'DifferentialDAO',
'DifferentialDiffContentMail' => 'DifferentialMail',
'DifferentialDiffCreateController' => 'DifferentialController',
'DifferentialDiffProperty' => 'DifferentialDAO',
'DifferentialDiffTableOfContentsView' => 'AphrontView',
'DifferentialDiffViewController' => 'DifferentialController',
'DifferentialExceptionMail' => 'DifferentialMail',
'DifferentialHunk' => 'DifferentialDAO',
'DifferentialInlineComment' => 'DifferentialDAO',
'DifferentialInlineCommentEditController' => 'DifferentialController',
'DifferentialInlineCommentPreviewController' => 'DifferentialController',
'DifferentialInlineCommentView' => 'AphrontView',
'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail',
'DifferentialPrimaryPaneView' => 'AphrontView',
'DifferentialReplyHandler' => 'PhabricatorMailReplyHandler',
'DifferentialReviewRequestMail' => 'DifferentialMail',
'DifferentialRevision' => 'DifferentialDAO',
'DifferentialRevisionCommentListView' => 'AphrontView',
'DifferentialRevisionCommentView' => 'AphrontView',
'DifferentialRevisionDetailView' => 'AphrontView',
'DifferentialRevisionEditController' => 'DifferentialController',
'DifferentialRevisionListController' => 'DifferentialController',
'DifferentialRevisionUpdateHistoryView' => 'AphrontView',
'DifferentialRevisionViewController' => 'DifferentialController',
'DifferentialSubscribeController' => 'DifferentialController',
'DifferentialViewTime' => 'DifferentialDAO',
'DiffusionBranchTableView' => 'DiffusionView',
'DiffusionBrowseController' => 'DiffusionController',
'DiffusionBrowseFileController' => 'DiffusionController',
'DiffusionBrowseTableView' => 'DiffusionView',
'DiffusionChangeController' => 'DiffusionController',
'DiffusionCommitChangeTableView' => 'DiffusionView',
'DiffusionCommitController' => 'DiffusionController',
'DiffusionController' => 'PhabricatorController',
'DiffusionDiffController' => 'DiffusionController',
'DiffusionGitBranchQuery' => 'DiffusionBranchQuery',
'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery',
'DiffusionGitDiffQuery' => 'DiffusionDiffQuery',
'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionGitHistoryQuery' => 'DiffusionHistoryQuery',
'DiffusionGitLastModifiedQuery' => 'DiffusionLastModifiedQuery',
'DiffusionGitRequest' => 'DiffusionRequest',
'DiffusionHistoryController' => 'DiffusionController',
'DiffusionHistoryTableView' => 'DiffusionView',
'DiffusionHomeController' => 'DiffusionController',
'DiffusionLastModifiedController' => 'DiffusionController',
'DiffusionPathCompleteController' => 'DiffusionController',
'DiffusionPathValidateController' => 'DiffusionController',
'DiffusionRepositoryController' => 'DiffusionController',
'DiffusionSvnBrowseQuery' => 'DiffusionBrowseQuery',
'DiffusionSvnDiffQuery' => 'DiffusionDiffQuery',
'DiffusionSvnFileContentQuery' => 'DiffusionFileContentQuery',
'DiffusionSvnHistoryQuery' => 'DiffusionHistoryQuery',
'DiffusionSvnLastModifiedQuery' => 'DiffusionLastModifiedQuery',
'DiffusionSvnRequest' => 'DiffusionRequest',
'DiffusionView' => 'AphrontView',
'HeraldAction' => 'HeraldDAO',
'HeraldApplyTranscript' => 'HeraldDAO',
'HeraldCommitAdapter' => 'HeraldObjectAdapter',
'HeraldCondition' => 'HeraldDAO',
'HeraldController' => 'PhabricatorController',
'HeraldDAO' => 'PhabricatorLiskDAO',
'HeraldDeleteController' => 'HeraldController',
'HeraldDifferentialRevisionAdapter' => 'HeraldObjectAdapter',
'HeraldDryRunAdapter' => 'HeraldObjectAdapter',
'HeraldHomeController' => 'HeraldController',
'HeraldNewController' => 'HeraldController',
'HeraldRule' => 'HeraldDAO',
'HeraldRuleController' => 'HeraldController',
'HeraldTestConsoleController' => 'HeraldController',
'HeraldTranscript' => 'HeraldDAO',
'HeraldTranscriptController' => 'HeraldController',
'HeraldTranscriptListController' => 'HeraldController',
'LiskIsolationTestCase' => 'PhabricatorTestCase',
'LiskIsolationTestDAO' => 'LiskDAO',
'ManiphestController' => 'PhabricatorController',
'ManiphestDAO' => 'PhabricatorLiskDAO',
'ManiphestReplyHandler' => 'PhabricatorMailReplyHandler',
'ManiphestTask' => 'ManiphestDAO',
'ManiphestTaskDescriptionChangeController' => 'ManiphestController',
'ManiphestTaskDetailController' => 'ManiphestController',
'ManiphestTaskEditController' => 'ManiphestController',
'ManiphestTaskListController' => 'ManiphestController',
'ManiphestTaskListView' => 'AphrontView',
'ManiphestTaskSummaryView' => 'AphrontView',
'ManiphestTransaction' => 'ManiphestDAO',
'ManiphestTransactionDetailView' => 'AphrontView',
'ManiphestTransactionListView' => 'AphrontView',
'ManiphestTransactionPreviewController' => 'ManiphestController',
'ManiphestTransactionSaveController' => 'ManiphestController',
'Phabricator404Controller' => 'PhabricatorController',
'PhabricatorAuthController' => 'PhabricatorController',
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO',
'PhabricatorConduitConsoleController' => 'PhabricatorConduitController',
'PhabricatorConduitController' => 'PhabricatorController',
'PhabricatorConduitDAO' => 'PhabricatorLiskDAO',
'PhabricatorConduitLogController' => 'PhabricatorConduitController',
'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO',
'PhabricatorController' => 'AphrontController',
'PhabricatorCountdownController' => 'PhabricatorController',
'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO',
'PhabricatorCountdownDeleteController' => 'PhabricatorCountdownController',
'PhabricatorCountdownEditController' => 'PhabricatorCountdownController',
'PhabricatorCountdownListController' => 'PhabricatorCountdownController',
'PhabricatorCountdownViewController' => 'PhabricatorCountdownController',
'PhabricatorDaemon' => 'PhutilDaemon',
'PhabricatorDaemonCombinedLogController' => 'PhabricatorDaemonController',
'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController',
'PhabricatorDaemonController' => 'PhabricatorController',
'PhabricatorDaemonDAO' => 'PhabricatorLiskDAO',
'PhabricatorDaemonLog' => 'PhabricatorDaemonDAO',
'PhabricatorDaemonLogEvent' => 'PhabricatorDaemonDAO',
'PhabricatorDaemonLogEventsView' => 'AphrontView',
'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController',
'PhabricatorDaemonLogListView' => 'AphrontView',
'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController',
'PhabricatorDaemonTimelineConsoleController' => 'PhabricatorDaemonController',
'PhabricatorDaemonTimelineEventController' => 'PhabricatorDaemonController',
'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO',
'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryCategoryListController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryController' => 'PhabricatorController',
'PhabricatorDirectoryDAO' => 'PhabricatorLiskDAO',
'PhabricatorDirectoryItem' => 'PhabricatorDirectoryDAO',
'PhabricatorDirectoryItemDeleteController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryItemListController' => 'PhabricatorDirectoryController',
'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController',
'PhabricatorDisabledUserController' => 'PhabricatorAuthController',
'PhabricatorDraft' => 'PhabricatorDraftDAO',
'PhabricatorDraftDAO' => 'PhabricatorLiskDAO',
'PhabricatorEditPreferencesController' => 'PhabricatorPreferencesController',
'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
'PhabricatorEmailTokenController' => 'PhabricatorAuthController',
'PhabricatorFile' => 'PhabricatorFileDAO',
'PhabricatorFileController' => 'PhabricatorController',
'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
'PhabricatorFileDropUploadController' => 'PhabricatorFileController',
'PhabricatorFileImageMacro' => 'PhabricatorFileDAO',
'PhabricatorFileListController' => 'PhabricatorFileController',
'PhabricatorFileMacroDeleteController' => 'PhabricatorFileController',
'PhabricatorFileMacroEditController' => 'PhabricatorFileController',
'PhabricatorFileMacroListController' => 'PhabricatorFileController',
'PhabricatorFileProxyController' => 'PhabricatorFileController',
'PhabricatorFileProxyImage' => 'PhabricatorFileDAO',
'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO',
'PhabricatorFileTransformController' => 'PhabricatorFileController',
'PhabricatorFileUploadController' => 'PhabricatorFileController',
'PhabricatorFileViewController' => 'PhabricatorFileController',
'PhabricatorGoodForNothingWorker' => 'PhabricatorWorker',
'PhabricatorHelpController' => 'PhabricatorController',
'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController',
'PhabricatorIRCBot' => 'PhabricatorDaemon',
'PhabricatorIRCObjectNameHandler' => 'PhabricatorIRCHandler',
'PhabricatorIRCProtocolHandler' => 'PhabricatorIRCHandler',
'PhabricatorJavelinLinter' => 'ArcanistLinter',
'PhabricatorLintEngine' => 'PhutilLintEngine',
'PhabricatorLiskDAO' => 'LiskDAO',
'PhabricatorLoginController' => 'PhabricatorAuthController',
'PhabricatorLogoutController' => 'PhabricatorAuthController',
'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMetaMTAController' => 'PhabricatorController',
'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
'PhabricatorMetaMTADaemon' => 'PhabricatorDaemon',
'PhabricatorMetaMTAEmailBodyParserTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAListController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase',
'PhabricatorMetaMTAMailingList' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTAMailingListEditController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMailingListsController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAReceiveController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAReceivedListController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO',
'PhabricatorMetaMTASendController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTASendGridReceiveController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAViewController' => 'PhabricatorMetaMTAController',
'PhabricatorOAuthDefaultRegistrationController' => 'PhabricatorOAuthRegistrationController',
'PhabricatorOAuthDiagnosticsController' => 'PhabricatorAuthController',
'PhabricatorOAuthFailureView' => 'AphrontView',
'PhabricatorOAuthLoginController' => 'PhabricatorAuthController',
'PhabricatorOAuthProviderFacebook' => 'PhabricatorOAuthProvider',
'PhabricatorOAuthProviderGithub' => 'PhabricatorOAuthProvider',
'PhabricatorOAuthRegistrationController' => 'PhabricatorAuthController',
'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController',
'PhabricatorOwnersController' => 'PhabricatorController',
'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO',
'PhabricatorOwnersDeleteController' => 'PhabricatorOwnersController',
'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController',
'PhabricatorOwnersEditController' => 'PhabricatorOwnersController',
'PhabricatorOwnersListController' => 'PhabricatorOwnersController',
'PhabricatorOwnersOwner' => 'PhabricatorOwnersDAO',
'PhabricatorOwnersPackage' => 'PhabricatorOwnersDAO',
'PhabricatorOwnersPath' => 'PhabricatorOwnersDAO',
'PhabricatorPHID' => 'PhabricatorPHIDDAO',
'PhabricatorPHIDAllocateController' => 'PhabricatorPHIDController',
'PhabricatorPHIDController' => 'PhabricatorController',
'PhabricatorPHIDDAO' => 'PhabricatorLiskDAO',
'PhabricatorPHIDListController' => 'PhabricatorPHIDController',
'PhabricatorPHIDLookupController' => 'PhabricatorPHIDController',
'PhabricatorPaste' => 'PhabricatorPasteDAO',
'PhabricatorPasteController' => 'PhabricatorController',
'PhabricatorPasteCreateController' => 'PhabricatorPasteController',
'PhabricatorPasteDAO' => 'PhabricatorLiskDAO',
'PhabricatorPasteListController' => 'PhabricatorPasteController',
'PhabricatorPasteViewController' => 'PhabricatorPasteController',
'PhabricatorPeopleController' => 'PhabricatorController',
'PhabricatorPeopleEditController' => 'PhabricatorPeopleController',
'PhabricatorPeopleListController' => 'PhabricatorPeopleController',
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController',
'PhabricatorPeopleProfileEditController' => 'PhabricatorPeopleController',
'PhabricatorPreferencesController' => 'PhabricatorController',
'PhabricatorProject' => 'PhabricatorProjectDAO',
'PhabricatorProjectAffiliation' => 'PhabricatorProjectDAO',
'PhabricatorProjectAffiliationEditController' => 'PhabricatorProjectController',
'PhabricatorProjectController' => 'PhabricatorController',
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
'PhabricatorProjectEditController' => 'PhabricatorProjectController',
'PhabricatorProjectListController' => 'PhabricatorProjectController',
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
'PhabricatorProjectQuickCreateController' => 'PhabricatorProjectController',
'PhabricatorRedirectController' => 'PhabricatorController',
'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName',
'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleImageMacro' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleManiphest' => 'PhabricatorRemarkupRuleObjectName',
'PhabricatorRemarkupRuleObjectName' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleProxyImage' => 'PhutilRemarkupRule',
'PhabricatorRemarkupRuleYoutube' => 'PhutilRemarkupRule',
'PhabricatorRepository' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryArcanistProject' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryArcanistProjectEditController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryCommit' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommitDiscoveryDaemon' => 'PhabricatorRepositoryDaemon',
'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker',
'PhabricatorRepositoryCommitTaskDaemon' => 'PhabricatorRepositoryDaemon',
'PhabricatorRepositoryController' => 'PhabricatorController',
'PhabricatorRepositoryCreateController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO',
'PhabricatorRepositoryDaemon' => 'PhabricatorDaemon',
'PhabricatorRepositoryDefaultCommitMessageDetailParser' => 'PhabricatorRepositoryCommitMessageDetailParser',
'PhabricatorRepositoryDeleteController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryEditController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorRepositoryGitFetchDaemon' => 'PhabricatorRepositoryDaemon',
'PhabricatorRepositoryGitHubNotification' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryGitHubPostReceiveController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryListController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryShortcut' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker',
'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon',
'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker',
'PhabricatorSearchAttachController' => 'PhabricatorSearchController',
'PhabricatorSearchBaseController' => 'PhabricatorController',
'PhabricatorSearchController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchDAO' => 'PhabricatorLiskDAO',
'PhabricatorSearchDifferentialIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSearchDocument' => 'PhabricatorSearchDAO',
'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO',
'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO',
'PhabricatorSearchManiphestIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSearchMySQLExecutor' => 'PhabricatorSearchExecutor',
'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
'PhabricatorSearchSelectController' => 'PhabricatorSearchController',
'PhabricatorStandardPageView' => 'AphrontPageView',
'PhabricatorStatusController' => 'PhabricatorController',
'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon',
'PhabricatorTestCase' => 'ArcanistPhutilTestCase',
'PhabricatorTimelineCursor' => 'PhabricatorTimelineDAO',
'PhabricatorTimelineDAO' => 'PhabricatorLiskDAO',
'PhabricatorTimelineEvent' => 'PhabricatorTimelineDAO',
'PhabricatorTimelineEventData' => 'PhabricatorTimelineDAO',
'PhabricatorTimer' => 'PhabricatorCountdownDAO',
'PhabricatorTransformedFile' => 'PhabricatorFileDAO',
'PhabricatorTypeaheadCommonDatasourceController' => 'PhabricatorTypeaheadDatasourceController',
'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController',
'PhabricatorUIExampleController' => 'PhabricatorController',
'PhabricatorUIExampleRenderController' => 'PhabricatorUIExampleController',
'PhabricatorUIListFilterExample' => 'PhabricatorUIExample',
'PhabricatorUIPagerExample' => 'PhabricatorUIExample',
'PhabricatorUser' => 'PhabricatorUserDAO',
'PhabricatorUserDAO' => 'PhabricatorLiskDAO',
'PhabricatorUserLog' => 'PhabricatorUserDAO',
'PhabricatorUserOAuthInfo' => 'PhabricatorUserDAO',
'PhabricatorUserPreferences' => 'PhabricatorUserDAO',
'PhabricatorUserProfile' => 'PhabricatorUserDAO',
'PhabricatorUserSettingsController' => 'PhabricatorPeopleController',
'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO',
'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO',
'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO',
'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController',
'PhabricatorXHPASTViewController' => 'PhabricatorController',
'PhabricatorXHPASTViewDAO' => 'PhabricatorLiskDAO',
'PhabricatorXHPASTViewFrameController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewFramesetController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewInputController' => 'PhabricatorXHPASTViewPanelController',
'PhabricatorXHPASTViewPanelController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewParseTree' => 'PhabricatorXHPASTViewDAO',
'PhabricatorXHPASTViewRunController' => 'PhabricatorXHPASTViewController',
'PhabricatorXHPASTViewStreamController' => 'PhabricatorXHPASTViewPanelController',
'PhabricatorXHPASTViewTreeController' => 'PhabricatorXHPASTViewPanelController',
'PhabricatorXHProfController' => 'PhabricatorController',
'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController',
'PhabricatorXHProfProfileSymbolView' => 'AphrontView',
'PhabricatorXHProfProfileTopLevelView' => 'AphrontView',
),
'requires_interface' =>
array(
),
));
diff --git a/src/applications/diffusion/controller/commit/DiffusionCommitController.php b/src/applications/diffusion/controller/commit/DiffusionCommitController.php
index ed34a9bf65..7958195639 100644
--- a/src/applications/diffusion/controller/commit/DiffusionCommitController.php
+++ b/src/applications/diffusion/controller/commit/DiffusionCommitController.php
@@ -1,255 +1,256 @@
<?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 DiffusionCommitController extends DiffusionController {
const CHANGES_LIMIT = 100;
public function processRequest() {
$drequest = $this->getDiffusionRequest();
$request = $this->getRequest();
+ $user = $request->getUser();
$callsign = $drequest->getRepository()->getCallsign();
$content = array();
$content[] = $this->buildCrumbs(array(
'commit' => true,
));
$detail_panel = new AphrontPanelView();
$repository = $drequest->getRepository();
$commit = $drequest->loadCommit();
if (!$commit) {
// TODO: Make more user-friendly.
throw new Exception('This commit has not parsed yet.');
}
$commit_data = $drequest->loadCommitData();
$factory = new DifferentialMarkupEngineFactory();
$engine = $factory->newDifferentialCommentMarkupEngine();
require_celerity_resource('diffusion-commit-view-css');
require_celerity_resource('phabricator-remarkup-css');
$property_table = $this->renderPropertyTable($commit, $commit_data);
$detail_panel->appendChild(
'<div class="diffusion-commit-view">'.
'<div class="diffusion-commit-dateline">'.
'r'.$callsign.$commit->getCommitIdentifier().
' &middot; '.
- date('F jS, Y g:i A', $commit->getEpoch()).
+ phabricator_datetime($commit->getEpoch(), $user).
'</div>'.
'<h1>Revision Detail</h1>'.
'<div class="diffusion-commit-details">'.
$property_table.
'<hr />'.
'<div class="diffusion-commit-message phabricator-remarkup">'.
$engine->markupText($commit_data->getCommitMessage()).
'</div>'.
'</div>'.
'</div>');
$content[] = $detail_panel;
$change_query = DiffusionPathChangeQuery::newFromDiffusionRequest(
$drequest);
$changes = $change_query->loadChanges();
$original_changes_count = count($changes);
if ($request->getStr('show_all') !== 'true' &&
$original_changes_count > self::CHANGES_LIMIT) {
$changes = array_slice($changes, 0, self::CHANGES_LIMIT);
}
$change_table = new DiffusionCommitChangeTableView();
$change_table->setDiffusionRequest($drequest);
$change_table->setPathChanges($changes);
$count = count($changes);
$bad_commit = null;
if ($count == 0) {
$bad_commit = queryfx_one(
id(new PhabricatorRepository())->establishConnection('r'),
'SELECT * FROM %T WHERE fullCommitName = %s',
PhabricatorRepository::TABLE_BADCOMMIT,
'r'.$callsign.$commit->getCommitIdentifier());
}
if ($bad_commit) {
$error_panel = new AphrontErrorView();
$error_panel->setWidth(AphrontErrorView::WIDTH_WIDE);
$error_panel->setTitle('Bad Commit');
$error_panel->appendChild(
phutil_escape_html($bad_commit['description']));
$content[] = $error_panel;
} else {
$change_panel = new AphrontPanelView();
$change_panel->setHeader("Changes (".number_format($count).")");
if ($count !== $original_changes_count) {
$show_all_button = phutil_render_tag(
'a',
array(
'class' => 'button green',
'href' => '?show_all=true',
),
phutil_escape_html('Show All Changes'));
$warning_view = id(new AphrontErrorView())
->setSeverity(AphrontErrorView::SEVERITY_WARNING)
->setTitle(sprintf(
"Showing only the first %d changes out of %s!",
self::CHANGES_LIMIT,
number_format($original_changes_count)));
$change_panel->appendChild($warning_view);
$change_panel->addButton($show_all_button);
}
$change_panel->appendChild($change_table);
$content[] = $change_panel;
if ($changes) {
$changesets = DiffusionPathChange::convertToDifferentialChangesets(
$changes);
$vcs = $repository->getVersionControlSystem();
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
$vcs_supports_directory_changes = true;
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$vcs_supports_directory_changes = false;
break;
default:
throw new Exception("Unknown VCS.");
}
$references = array();
foreach ($changesets as $key => $changeset) {
$file_type = $changeset->getFileType();
if ($file_type == DifferentialChangeType::FILE_DIRECTORY) {
if (!$vcs_supports_directory_changes) {
unset($changesets[$key]);
continue;
}
}
$branch = $drequest->getBranchURIComponent(
$drequest->getBranch());
$filename = $changeset->getFilename();
$commit = $drequest->getCommit();
$reference = "{$branch}{$filename};{$commit}";
$references[$key] = $reference;
}
$change_list = new DifferentialChangesetListView();
$change_list->setChangesets($changesets);
$change_list->setRenderingReferences($references);
$change_list->setRenderURI('/diffusion/'.$callsign.'/diff/');
// TODO: This is pretty awkward, unify the CSS between Diffusion and
// Differential better.
require_celerity_resource('differential-core-view-css');
$change_list =
'<div class="differential-primary-pane">'.
$change_list->render().
'</div>';
} else {
$change_list =
'<div style="margin: 2em; color: #666; padding: 1em;
background: #eee;">'.
'(no changes blah blah)'.
'</div>';
}
$content[] = $change_list;
}
return $this->buildStandardPageResponse(
$content,
array(
'title' => 'Diffusion',
));
}
private function renderPropertyTable(
PhabricatorRepositoryCommit $commit,
PhabricatorRepositoryCommitData $data) {
$phids = array();
if ($data->getCommitDetail('authorPHID')) {
$phids[] = $data->getCommitDetail('authorPHID');
}
if ($data->getCommitDetail('reviewerPHID')) {
$phids[] = $data->getCommitDetail('reviewerPHID');
}
if ($data->getCommitDetail('differential.revisionPHID')) {
$phids[] = $data->getCommitDetail('differential.revisionPHID');
}
$handles = array();
if ($phids) {
$handles = id(new PhabricatorObjectHandleData($phids))
->loadHandles();
}
$props = array();
$author_phid = $data->getCommitDetail('authorPHID');
if ($data->getCommitDetail('authorPHID')) {
$props['Author'] = $handles[$author_phid]->renderLink();
} else {
$props['Author'] = phutil_escape_html($data->getAuthorName());
}
$reviewer_phid = $data->getCommitDetail('reviewerPHID');
$reviewer_name = $data->getCommitDetail('reviewerName');
if ($reviewer_phid) {
$props['Reviewer'] = $handles[$reviewer_phid]->renderLink();
} else if ($reviewer_name) {
$props['Reviewer'] = phutil_escape_html($reviewer_name);
}
$revision_phid = $data->getCommitDetail('differential.revisionPHID');
if ($revision_phid) {
$props['Differential Revision'] = $handles[$revision_phid]->renderLink();
}
$rows = array();
foreach ($props as $key => $value) {
$rows[] =
'<tr>'.
'<th>'.$key.':</th>'.
'<td>'.$value.'</td>'.
'</tr>';
}
return
'<table class="diffusion-commit-properties">'.
implode("\n", $rows).
'</table>';
}
}
diff --git a/src/applications/diffusion/controller/commit/__init__.php b/src/applications/diffusion/controller/commit/__init__.php
index 60201c6b8a..70cfe04c4c 100644
--- a/src/applications/diffusion/controller/commit/__init__.php
+++ b/src/applications/diffusion/controller/commit/__init__.php
@@ -1,28 +1,29 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/differential/constants/changetype');
phutil_require_module('phabricator', 'applications/differential/parser/markup');
phutil_require_module('phabricator', 'applications/differential/view/changesetlistview');
phutil_require_module('phabricator', 'applications/diffusion/controller/base');
phutil_require_module('phabricator', 'applications/diffusion/data/pathchange');
phutil_require_module('phabricator', 'applications/diffusion/query/pathchange/base');
phutil_require_module('phabricator', 'applications/diffusion/view/commitchangetable');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
phutil_require_module('phabricator', 'applications/repository/storage/repository');
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionCommitController.php');
diff --git a/src/applications/diffusion/controller/home/DiffusionHomeController.php b/src/applications/diffusion/controller/home/DiffusionHomeController.php
index 0caf98370b..c5b7dc1605 100644
--- a/src/applications/diffusion/controller/home/DiffusionHomeController.php
+++ b/src/applications/diffusion/controller/home/DiffusionHomeController.php
@@ -1,161 +1,163 @@
<?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 DiffusionHomeController extends DiffusionController {
public function processRequest() {
+ $request = $this->getRequest();
+ $user = $request->getUser();
$shortcuts = id(new PhabricatorRepositoryShortcut())->loadAll();
if ($shortcuts) {
$shortcuts = msort($shortcuts, 'getSequence');
$rows = array();
foreach ($shortcuts as $shortcut) {
$rows[] = array(
phutil_render_tag(
'a',
array(
'href' => $shortcut->getHref(),
),
phutil_escape_html($shortcut->getName())),
phutil_escape_html($shortcut->getDescription()),
);
}
$shortcut_table = new AphrontTableView($rows);
$shortcut_table->setHeaders(
array(
'Link',
'',
));
$shortcut_table->setColumnClasses(
array(
'pri',
'wide',
));
$shortcut_panel = new AphrontPanelView();
$shortcut_panel->setHeader('Shortcuts');
$shortcut_panel->appendChild($shortcut_table);
} else {
$shortcut_panel = null;
}
$repository = new PhabricatorRepository();
$repositories = $repository->loadAll();
foreach ($repositories as $key => $repository) {
if (!$repository->getDetail('tracking-enabled')) {
unset($repositories[$key]);
}
}
$repository_ids = mpull($repositories, 'getID');
$summaries = array();
$commits = array();
if ($repository_ids) {
$summaries = queryfx_all(
$repository->establishConnection('r'),
'SELECT * FROM %T WHERE repositoryID IN (%Ld)',
PhabricatorRepository::TABLE_SUMMARY,
$repository_ids);
$summaries = ipull($summaries, null, 'repositoryID');
$commit_ids = array_filter(ipull($summaries, 'lastCommitID'));
if ($commit_ids) {
$commit = new PhabricatorRepositoryCommit();
$commits = $commit->loadAllWhere('id IN (%Ld)', $commit_ids);
$commits = mpull($commits, null, 'getRepositoryID');
}
}
$rows = array();
foreach ($repositories as $repository) {
$id = $repository->getID();
$commit = idx($commits, $id);
$size = idx(idx($summaries, $id, array()), 'size', 0);
$date = '-';
$time = '-';
if ($commit) {
- $date = date('M j, Y', $commit->getEpoch());
- $time = date('g:i A', $commit->getEpoch());
+ $date = phabricator_date($commit->getEpoch(), $user);
+ $time = phabricator_time($commit->getEpoch(), $user);
}
$rows[] = array(
phutil_render_tag(
'a',
array(
'href' => '/diffusion/'.$repository->getCallsign().'/',
),
phutil_escape_html($repository->getName())),
phutil_escape_html($repository->getDetail('description')),
PhabricatorRepositoryType::getNameForRepositoryType(
$repository->getVersionControlSystem()),
$size ? number_format($size) : '-',
$commit
? DiffusionView::linkCommit(
$repository,
$commit->getCommitIdentifier())
: '-',
$date,
$time,
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'Repository',
'Description',
'VCS',
'Size',
'Last',
'Date',
'Time',
));
$table->setColumnClasses(
array(
'pri',
'wide',
'',
'n',
'n',
'',
'right',
));
$panel = new AphrontPanelView();
$panel->setHeader('Browse Repositories');
$panel->appendChild($table);
$crumbs = $this->buildCrumbs();
return $this->buildStandardPageResponse(
array(
$crumbs,
$shortcut_panel,
$panel,
),
array(
'title' => 'Diffusion',
));
}
}
diff --git a/src/applications/diffusion/controller/home/__init__.php b/src/applications/diffusion/controller/home/__init__.php
index 56eca20496..af813ab9f4 100644
--- a/src/applications/diffusion/controller/home/__init__.php
+++ b/src/applications/diffusion/controller/home/__init__.php
@@ -1,23 +1,24 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/diffusion/controller/base');
phutil_require_module('phabricator', 'applications/diffusion/view/base');
phutil_require_module('phabricator', 'applications/repository/constants/repositorytype');
phutil_require_module('phabricator', 'applications/repository/storage/commit');
phutil_require_module('phabricator', 'applications/repository/storage/repository');
phutil_require_module('phabricator', 'applications/repository/storage/shortcut');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('DiffusionHomeController.php');
diff --git a/src/applications/herald/controller/transcriptlist/HeraldTranscriptListController.php b/src/applications/herald/controller/transcriptlist/HeraldTranscriptListController.php
index db69b1612f..c465655c4d 100644
--- a/src/applications/herald/controller/transcriptlist/HeraldTranscriptListController.php
+++ b/src/applications/herald/controller/transcriptlist/HeraldTranscriptListController.php
@@ -1,150 +1,151 @@
<?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 HeraldTranscriptListController extends HeraldController {
public function processRequest() {
$request = $this->getRequest();
+ $user = $request->getUser();
// Get one page of data together with the pager.
// Pull these objects manually since the serialized fields are gigantic.
$transcript = new HeraldTranscript();
$conn_r = $transcript->establishConnection('r');
$phid = $request->getStr('phid');
$where_clause = '';
if ($phid) {
$where_clause = qsprintf(
$conn_r,
'WHERE objectPHID = %s',
$phid);
}
$offset = $request->getInt('offset', 0);
$page_size = 100;
$limit_clause = qsprintf(
$conn_r,
'LIMIT %d, %d',
$offset, $page_size + 1);
$data = queryfx_all(
$conn_r,
'SELECT id, objectPHID, time, duration, dryRun FROM %T
%Q
ORDER BY id DESC
%Q',
$transcript->getTableName(),
$where_clause,
$limit_clause);
$pager = new AphrontPagerView();
$pager->getPageSize($page_size);
$pager->setHasMorePages(count($data) == $page_size + 1);
$pager->setOffset($offset);
$pager->setURI($request->getRequestURI(), 'offset');
/*
$conn_r = smc_get_db('cdb.herald', 'r');
$page_size = 100;
$pager = new SimplePager();
$pager->setPageSize($page_size);
$pager->setOffset((((int)$request->getInt('page')) - 1) * $page_size);
$pager->order('id', array('id'));
$fbid = $request->getInt('fbid');
if ($fbid) {
$filter = qsprintf(
$conn_r,
'WHERE objectID = %d',
$fbid);
} else {
$filter = '';
}
$data = $pager->select(
$conn_r,
'id, objectID, time, duration, dryRun FROM transcript %Q',
$filter);
*/
// Render the table.
$handles = array();
if ($data) {
$phids = ipull($data, 'objectPHID', 'objectPHID');
$handles = id(new PhabricatorObjectHandleData($phids))
->loadHandles();
}
$rows = array();
foreach ($data as $xscript) {
$rows[] = array(
- date('F jS', $xscript['time']),
- date('g:i:s A', $xscript['time']),
+ phabricator_date($xscript['time'],$user),
+ phabricator_time($xscript['time'],$user),
$handles[$xscript['objectPHID']]->renderLink(),
$xscript['dryRun'] ? 'Yes' : '',
number_format((int)(1000 * $xscript['duration'])).' ms',
phutil_render_tag(
'a',
array(
'href' => '/herald/transcript/'.$xscript['id'].'/',
'class' => 'button small grey',
),
'View Transcript'),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'Date',
'Time',
'Object',
'Dry Run',
'Duration',
'View',
));
$table->setColumnClasses(
array(
'',
'right',
'wide wrap',
'',
'',
'action',
));
// Render the whole page.
$panel = new AphrontPanelView();
$panel->setHeader('Herald Transcripts');
$panel->appendChild($table);
$panel->appendChild($pager);
return $this->buildStandardPageResponse(
$panel,
array(
'title' => 'Herald Transcripts',
'tab' => 'transcripts',
));
}
}
diff --git a/src/applications/herald/controller/transcriptlist/__init__.php b/src/applications/herald/controller/transcriptlist/__init__.php
index 13aacd82dc..def5438def 100644
--- a/src/applications/herald/controller/transcriptlist/__init__.php
+++ b/src/applications/herald/controller/transcriptlist/__init__.php
@@ -1,22 +1,23 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/herald/controller/base');
phutil_require_module('phabricator', 'applications/herald/storage/transcript/base');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'storage/qsprintf');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/control/pager');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('HeraldTranscriptListController.php');
diff --git a/src/applications/metamta/controller/receivedlist/PhabricatorMetaMTAReceivedListController.php b/src/applications/metamta/controller/receivedlist/PhabricatorMetaMTAReceivedListController.php
index 937054e6b3..5ff2093ba5 100644
--- a/src/applications/metamta/controller/receivedlist/PhabricatorMetaMTAReceivedListController.php
+++ b/src/applications/metamta/controller/receivedlist/PhabricatorMetaMTAReceivedListController.php
@@ -1,93 +1,94 @@
<?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 PhabricatorMetaMTAReceivedListController
extends PhabricatorMetaMTAController {
public function processRequest() {
$request = $this->getRequest();
+ $user = $request->getUser();
$pager = new AphrontPagerView();
$pager->setOffset($request->getInt('page'));
$pager->setURI($request->getRequestURI(), 'page');
$mails = id(new PhabricatorMetaMTAReceivedMail())->loadAllWhere(
'1 = 1 ORDER BY id DESC LIMIT %d, %d',
$pager->getOffset(),
$pager->getPageSize() + 1);
$mails = $pager->sliceResults($mails);
$phids = array_merge(
mpull($mails, 'getAuthorPHID'),
mpull($mails, 'getRelatedPHID')
);
$phids = array_unique(array_filter($phids));
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$rows = array();
foreach ($mails as $mail) {
$rows[] = array(
$mail->getID(),
- date('M jS Y', $mail->getDateCreated()),
- date('g:i:s A', $mail->getDateCreated()),
+ phabricator_date($mail->getDateCreated(), $user),
+ phabricator_time($mail->getDateCreated(), $user),
$mail->getAuthorPHID()
? $handles[$mail->getAuthorPHID()]->renderLink()
: '-',
$mail->getRelatedPHID()
? $handles[$mail->getRelatedPHID()]->renderLink()
: '-',
phutil_escape_html($mail->getMessage()),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'ID',
'Date',
'Time',
'Author',
'Object',
'Message',
));
$table->setColumnClasses(
array(
null,
null,
'right',
null,
null,
'wide',
));
$panel = new AphrontPanelView();
$panel->setHeader('Received Mail');
$panel->setCreateButton('Test Receiver', '/mail/receive/');
$panel->appendChild($table);
$panel->appendChild($pager);
return $this->buildStandardPageResponse(
$panel,
array(
'title' => 'Received Mail',
'tab' => 'received',
));
}
}
diff --git a/src/applications/metamta/controller/receivedlist/__init__.php b/src/applications/metamta/controller/receivedlist/__init__.php
index c111e1ef8f..36de24ff4a 100644
--- a/src/applications/metamta/controller/receivedlist/__init__.php
+++ b/src/applications/metamta/controller/receivedlist/__init__.php
@@ -1,20 +1,21 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/metamta/controller/base');
phutil_require_module('phabricator', 'applications/metamta/storage/receivedmail');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'view/control/pager');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorMetaMTAReceivedListController.php');
diff --git a/src/applications/metamta/controller/view/PhabricatorMetaMTAViewController.php b/src/applications/metamta/controller/view/PhabricatorMetaMTAViewController.php
index 8d716d8331..627cf6ae36 100644
--- a/src/applications/metamta/controller/view/PhabricatorMetaMTAViewController.php
+++ b/src/applications/metamta/controller/view/PhabricatorMetaMTAViewController.php
@@ -1,82 +1,83 @@
<?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 PhabricatorMetaMTAViewController extends PhabricatorMetaMTAController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
+ $user = $request->getUser();
$mail = id(new PhabricatorMetaMTAMail())->load($this->id);
if (!$mail) {
return new Aphront404Response();
}
$status = PhabricatorMetaMTAMail::getReadableStatus($mail->getStatus());
$form = new AphrontFormView();
$form->setUser($request->getUser());
$form->setAction('/mail/send/');
$form
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Subject')
->setValue($mail->getSubject()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Created')
- ->setValue(date('F jS, Y g:i:s A', $mail->getDateCreated())))
+ ->setValue(phabricator_datetime($mail->getDateCreated(), $user)))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Status')
->setValue($status))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Message')
->setValue($mail->getMessage()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Related PHID')
->setValue($mail->getRelatedPHID()))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Parameters')
->setValue(json_encode($mail->getParameters())))
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton('/mail/', 'Done'));
$panel = new AphrontPanelView();
$panel->setHeader('View Email');
$panel->appendChild($form);
$panel->setWidth(AphrontPanelView::WIDTH_WIDE);
return $this->buildStandardPageResponse(
$panel,
array(
'title' => 'View Mail',
));
}
}
diff --git a/src/applications/metamta/controller/view/__init__.php b/src/applications/metamta/controller/view/__init__.php
index 17e87a642e..d08f948405 100644
--- a/src/applications/metamta/controller/view/__init__.php
+++ b/src/applications/metamta/controller/view/__init__.php
@@ -1,21 +1,22 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/404');
phutil_require_module('phabricator', 'applications/metamta/controller/base');
phutil_require_module('phabricator', 'applications/metamta/storage/mail');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/static');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorMetaMTAViewController.php');
diff --git a/src/applications/people/controller/list/PhabricatorPeopleListController.php b/src/applications/people/controller/list/PhabricatorPeopleListController.php
index e3e69e8150..e5f2d6b81e 100644
--- a/src/applications/people/controller/list/PhabricatorPeopleListController.php
+++ b/src/applications/people/controller/list/PhabricatorPeopleListController.php
@@ -1,126 +1,126 @@
<?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 PhabricatorPeopleListController extends PhabricatorPeopleController {
public function processRequest() {
$request = $this->getRequest();
$is_admin = $request->getUser()->getIsAdmin();
$user = new PhabricatorUser();
$count = queryfx_one(
$user->establishConnection('r'),
'SELECT COUNT(*) N FROM %T',
$user->getTableName());
$count = idx($count, 'N', 0);
$pager = new AphrontPagerView();
$pager->setOffset($request->getInt('page', 0));
$pager->setCount($count);
$pager->setURI($request->getRequestURI(), 'page');
$users = id(new PhabricatorUser())->loadAllWhere(
'1 = 1 ORDER BY id DESC LIMIT %d, %d',
$pager->getOffset(),
$pager->getPageSize());
$rows = array();
foreach ($users as $user) {
$status = '';
if ($user->getIsDisabled()) {
$status = 'Disabled';
} else if ($user->getIsAdmin()) {
$status = 'Admin';
} else {
$status = '-';
}
$rows[] = array(
- date('M jS, Y', $user->getDateCreated()),
- date('g:i:s A', $user->getDateCreated()),
+ phabricator_date($user->getDateCreated(), $user),
+ phabricator_time($user->getDateCreated(), $user),
phutil_render_tag(
'a',
array(
'href' => '/p/'.$user->getUsername().'/',
),
phutil_escape_html($user->getUserName())),
phutil_escape_html($user->getRealName()),
$status,
phutil_render_tag(
'a',
array(
'class' => 'button grey small',
'href' => '/people/edit/'.$user->getID().'/',
),
'Administrate User'),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'Join Date',
'Time',
'Username',
'Real Name',
'Status',
'',
));
$table->setColumnClasses(
array(
null,
'right',
'pri',
'wide',
null,
'action',
));
$table->setColumnVisibility(
array(
true,
true,
true,
true,
$is_admin,
$is_admin,
));
$panel = new AphrontPanelView();
$panel->setHeader('People ('.number_format($count).')');
$panel->appendChild($table);
$panel->appendChild($pager);
if ($is_admin) {
$panel->addButton(
phutil_render_tag(
'a',
array(
'href' => '/people/edit/',
'class' => 'button green',
),
'Create New Account'));
}
return $this->buildStandardPageResponse($panel, array(
'title' => 'People',
'tab' => 'directory',
));
}
}
diff --git a/src/applications/people/controller/list/__init__.php b/src/applications/people/controller/list/__init__.php
index 364bc2dda9..13eb127ea5 100644
--- a/src/applications/people/controller/list/__init__.php
+++ b/src/applications/people/controller/list/__init__.php
@@ -1,20 +1,21 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/people/controller/base');
phutil_require_module('phabricator', 'applications/people/storage/user');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/control/pager');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorPeopleListController.php');
diff --git a/src/applications/people/controller/logs/PhabricatorPeopleLogsController.php b/src/applications/people/controller/logs/PhabricatorPeopleLogsController.php
index 33810fc3b9..545a2ee27c 100644
--- a/src/applications/people/controller/logs/PhabricatorPeopleLogsController.php
+++ b/src/applications/people/controller/logs/PhabricatorPeopleLogsController.php
@@ -1,244 +1,244 @@
<?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 PhabricatorPeopleLogsController extends PhabricatorPeopleController {
public function shouldRequireAdmin() {
return true;
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$filter_activity = $request->getStr('activity');
$filter_ip = $request->getStr('ip');
$filter_session = $request->getStr('session');
$filter_user = $request->getArr('user', array());
$filter_actor = $request->getArr('actor', array());
$user_value = array();
$actor_value = array();
$phids = array_merge($filter_user, $filter_actor);
if ($phids) {
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
if ($filter_user) {
$filter_user = reset($filter_user);
$user_value = array(
$filter_user => $handles[$filter_user]->getFullName(),
);
}
if ($filter_actor) {
$filter_actor = reset($filter_actor);
$actor_value = array(
$filter_actor => $handles[$filter_actor]->getFullName(),
);
}
}
$form = new AphrontFormView();
$form
->setUser($user)
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel('Filter Actor')
->setName('actor')
->setLimit(1)
->setValue($actor_value)
->setDatasource('/typeahead/common/accounts/'))
->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel('Filter User')
->setName('user')
->setLimit(1)
->setValue($user_value)
->setDatasource('/typeahead/common/accounts/'))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel('Show Activity')
->setName('activity')
->setValue($filter_activity)
->setOptions(
array(
'' => 'All Activity',
'admin' => 'Admin Activity',
)))
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Filter IP')
->setName('ip')
->setValue($filter_ip)
->setCaption(
'Enter an IP (or IP prefix) to show only activity by that remote '.
'address.'))
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Filter Session')
->setName('session')
->setValue($filter_session))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Filter Logs'));
$log_table = new PhabricatorUserLog();
$conn_r = $log_table->establishConnection('r');
$where_clause = array();
$where_clause[] = '1 = 1';
if ($filter_user) {
$where_clause[] = qsprintf(
$conn_r,
'userPHID = %s',
$filter_user);
}
if ($filter_actor) {
$where_clause[] = qsprintf(
$conn_r,
'actorPHID = %s',
$filter_actor);
}
if ($filter_activity == 'admin') {
$where_clause[] = qsprintf(
$conn_r,
'action NOT IN (%Ls)',
array(
PhabricatorUserLog::ACTION_LOGIN,
PhabricatorUserLog::ACTION_LOGOUT,
PhabricatorUserLog::ACTION_LOGIN_FAILURE,
));
}
if ($filter_ip) {
$where_clause[] = qsprintf(
$conn_r,
'remoteAddr LIKE %>',
$filter_ip);
}
if ($filter_session) {
$where_clause[] = qsprintf(
$conn_r,
'session = %s',
$filter_session);
}
$where_clause = '('.implode(') AND (', $where_clause).')';
$pager = new AphrontPagerView();
$pager->setURI($request->getRequestURI(), 'page');
$pager->setOffset($request->getInt('page'));
$pager->setPageSize(500);
$logs = $log_table->loadAllWhere(
'(%Q) ORDER BY dateCreated DESC LIMIT %d, %d',
$where_clause,
$pager->getOffset(),
$pager->getPageSize() + 1);
$logs = $pager->sliceResults($logs);
$phids = array();
foreach ($logs as $log) {
$phids[$log->getActorPHID()] = true;
$phids[$log->getUserPHID()] = true;
}
$phids = array_keys($phids);
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$rows = array();
foreach ($logs as $log) {
$rows[] = array(
- date('M jS, Y', $log->getDateCreated()),
- date('g:i:s A', $log->getDateCreated()),
+ phabricator_date($log->getDateCreated(),$user),
+ phabricator_time($log->getDateCreated(),$user),
$log->getAction(),
$log->getActorPHID()
? phutil_escape_html($handles[$log->getActorPHID()]->getName())
: null,
phutil_escape_html($handles[$log->getUserPHID()]->getName()),
json_encode($log->getOldValue(), true),
json_encode($log->getNewValue(), true),
phutil_render_tag(
'a',
array(
'href' => $request
->getRequestURI()
->alter('ip', $log->getRemoteAddr()),
),
phutil_escape_html($log->getRemoteAddr())),
phutil_render_tag(
'a',
array(
'href' => $request
->getRequestURI()
->alter('session', $log->getSession()),
),
phutil_escape_html($log->getSession())),
);
}
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
'Date',
'Time',
'Action',
'Actor',
'User',
'Old',
'New',
'IP',
'Session',
));
$table->setColumnClasses(
array(
'',
'right',
'',
'',
'',
'wrap',
'wrap',
'',
'wide',
));
$panel = new AphrontPanelView();
$panel->setHeader('Activity Logs');
$panel->appendChild($table);
$panel->appendChild($pager);
$filter = new AphrontListFilterView();
$filter->appendChild($form);
return $this->buildStandardPageResponse(
array(
$filter,
$panel,
),
array(
'title' => 'Activity Logs',
'tab' => 'logs',
));
}
}
diff --git a/src/applications/people/controller/logs/__init__.php b/src/applications/people/controller/logs/__init__.php
index 824368dac3..3490be2539 100644
--- a/src/applications/people/controller/logs/__init__.php
+++ b/src/applications/people/controller/logs/__init__.php
@@ -1,27 +1,28 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/people/controller/base');
phutil_require_module('phabricator', 'applications/people/storage/log');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'storage/qsprintf');
phutil_require_module('phabricator', 'view/control/pager');
phutil_require_module('phabricator', 'view/control/table');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/select');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/text');
phutil_require_module('phabricator', 'view/form/control/tokenizer');
phutil_require_module('phabricator', 'view/layout/listfilter');
phutil_require_module('phabricator', 'view/layout/panel');
+phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorPeopleLogsController.php');
diff --git a/src/applications/people/controller/settings/PhabricatorUserSettingsController.php b/src/applications/people/controller/settings/PhabricatorUserSettingsController.php
index 319066ffc2..d00ed87e66 100644
--- a/src/applications/people/controller/settings/PhabricatorUserSettingsController.php
+++ b/src/applications/people/controller/settings/PhabricatorUserSettingsController.php
@@ -1,537 +1,557 @@
<?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 PhabricatorUserSettingsController extends PhabricatorPeopleController {
private $page;
private $accountEditable;
public function willProcessRequest(array $data) {
$this->page = idx($data, 'page');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$pages = array(
'account' => 'Account',
'email' => 'Email',
// 'password' => 'Password',
'arcanist' => 'Arcanist Certificate',
);
$oauth_providers = PhabricatorOAuthProvider::getAllProviders();
foreach ($oauth_providers as $provider) {
if (!$provider->isProviderEnabled()) {
continue;
}
$key = $provider->getProviderKey();
$name = $provider->getProviderName();
$pages[$key] = $name.' Account';
}
if (empty($pages[$this->page])) {
$this->page = key($pages);
}
$account_editable = PhabricatorEnv::getEnvConfig('account.editable');
$this->accountEditable = $account_editable;
$e_realname = true;
$e_email = true;
$errors = array();
if ($request->isFormPost()) {
switch ($this->page) {
case 'email':
if (!$account_editable) {
return new Aphront400Response();
}
$user->setEmail($request->getStr('email'));
if (!strlen($user->getEmail())) {
$errors[] = 'You must enter an e-mail address';
$e_email = 'Required';
}
if (!$errors) {
$user->save();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/email/?saved=true');
}
break;
case 'arcanist':
if (!$request->isDialogFormPost()) {
$dialog = new AphrontDialogView();
$dialog->setUser($user);
$dialog->setTitle('Really regenerate session?');
$dialog->setSubmitURI('/settings/page/arcanist/');
$dialog->addSubmitButton('Regenerate');
$dialog->addCancelbutton('/settings/page/arcanist/');
$dialog->appendChild(
'<p>Really destroy the old certificate? Any established '.
'sessions will be terminated.');
return id(new AphrontDialogResponse())
->setDialog($dialog);
}
$conn = $user->establishConnection('w');
queryfx(
$conn,
'DELETE FROM %T WHERE userPHID = %s AND type LIKE %>',
PhabricatorUser::SESSION_TABLE,
$user->getPHID(),
'conduit');
// This implicitly regenerates the certificate.
$user->setConduitCertificate(null);
$user->save();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/arcanist/?regenerated=true');
break;
case 'account':
if (!$account_editable) {
return new Aphront400Response();
}
if (!empty($_FILES['profile'])) {
$err = idx($_FILES['profile'], 'error');
if ($err != UPLOAD_ERR_NO_FILE) {
$file = PhabricatorFile::newFromPHPUpload($_FILES['profile']);
$okay = $file->isTransformableImage();
if ($okay) {
$user->setProfileImagePHID($file->getPHID());
} else {
$errors[] =
'Only valid image files (jpg, jpeg, png or gif) '.
'will be accepted.';
}
}
}
$user->setRealName($request->getStr('realname'));
if (!strlen($user->getRealName())) {
$errors[] = 'Real name must be nonempty.';
$e_realname = 'Required';
}
+ $new_timezone = $request->getStr('timezone');
+ if (in_array($new_timezone, DateTimeZone::listIdentifiers(), true)) {
+ $user->setTimezoneIdentifier($new_timezone);
+ } else {
+ $errors[] =
+ 'The selected timezone is not a valid timezone.';
+ }
+
if (!$errors) {
$user->save();
return id(new AphrontRedirectResponse())
->setURI('/settings/page/account/?saved=true');
}
break;
}
}
switch ($this->page) {
case 'arcanist':
$content = $this->renderArcanistCertificateForm();
break;
case 'account':
$content = $this->renderAccountForm($errors, $e_realname);
break;
case 'email':
$content = $this->renderEmailForm($errors, $e_email);
break;
default:
if (empty($pages[$this->page])) {
return new Aphront404Response();
}
$content = $this->renderOAuthForm($oauth_providers[$this->page]);
break;
}
$sidenav = new AphrontSideNavView();
foreach ($pages as $page => $name) {
$sidenav->addNavItem(
phutil_render_tag(
'a',
array(
'href' => '/settings/page/'.$page.'/',
'class' => ($page == $this->page)
? 'aphront-side-nav-selected'
: null,
),
phutil_escape_html($name)));
}
$sidenav->appendChild($content);
return $this->buildStandardPageResponse(
$sidenav,
array(
'title' => 'Account Settings',
));
}
private function renderArcanistCertificateForm() {
$request = $this->getRequest();
$user = $request->getUser();
if ($request->getStr('regenerated')) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$notice->setTitle('Certificate Regenerated');
$notice->appendChild(
'<p>Your old certificate has been destroyed and you have been issued '.
'a new certificate. Sessions established under the old certificate '.
'are no longer valid.</p>');
$notice = $notice->render();
} else {
$notice = null;
}
$host = PhabricatorEnv::getEnvConfig('phabricator.base-uri') . 'api/';
$conduit_setting = sprintf(
' %s: {'."\n".
' "user" : %s,'."\n".
' "cert" : %s'."\n".
' }'."\n",
json_encode($host),
json_encode($user->getUserName()),
json_encode($user->getConduitCertificate()));
$cert_form = new AphrontFormView();
$cert_form
->setUser($user)
->appendChild(
'<p class="aphront-form-instructions">Copy and paste the host info '.
'including the certificate into your <tt>~/.arcrc</tt> in the "hosts" '.
'session to enable Arcanist to authenticate against this host.</p>')
->appendChild(
id(new AphrontFormMarkupControl())
->setControlStyle('white-space: pre; font-family: monospace')
->setValue(
'{'."\n".
' ...'."\n".
' "hosts" : {'."\n"))
->appendChild(
id(new AphrontFormTextAreaControl())
->setLabel('Credentials')
->setHeight(AphrontFormTextAreaControl::HEIGHT_SHORT)
->setControlStyle('font-family: monospace')
->setValue($conduit_setting))
->appendChild(
id(new AphrontFormStaticControl())
->setControlStyle('white-space: pre; font-family: monospace')
->setValue(
' }'."\n".
' ...'."\n".
'}'));
$cert = new AphrontPanelView();
$cert->setHeader('Arcanist Certificate');
$cert->appendChild($cert_form);
$cert->setWidth(AphrontPanelView::WIDTH_FORM);
$regen_form = new AphrontFormView();
$regen_form
->setUser($user)
->setAction('/settings/page/arcanist/')
->appendChild(
'<p class="aphront-form-instructions">You can regenerate this '.
'certificate, which will invalidate the old certificate and create '.
'a new one.</p>')
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Regenerate Certificate'));
$regen = new AphrontPanelView();
$regen->setHeader('Regenerate Certificate');
$regen->appendChild($regen_form);
$regen->setWidth(AphrontPanelView::WIDTH_FORM);
return $notice.$cert->render().$regen->render();
}
private function renderAccountForm(array $errors, $e_realname) {
$request = $this->getRequest();
$user = $request->getUser();
$img_src = PhabricatorFileURI::getViewURIForPHID(
$user->getProfileImagePHID());
$editable = $this->accountEditable;
$notice = null;
if (!$errors) {
if ($request->getStr('saved')) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$notice->setTitle('Changed Saved');
$notice->appendChild('<p>Your changes have been saved.</p>');
$notice = $notice->render();
}
} else {
$notice = new AphrontErrorView();
$notice->setTitle('Form Errors');
$notice->setErrors($errors);
$notice = $notice->render();
}
$form = new AphrontFormView();
$form
->setUser($user)
->setEncType('multipart/form-data')
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Username')
->setValue($user->getUsername()))
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Real Name')
->setName('realname')
->setError($e_realname)
->setValue($user->getRealName())
->setDisabled(!$editable))
->appendChild(
id(new AphrontFormMarkupControl())
->setValue('<hr />'))
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel('Profile Image')
->setValue(
phutil_render_tag(
'img',
array(
'src' => $img_src,
))));
if ($editable) {
+ $timezone_ids = DateTimeZone::listIdentifiers();
+ $timezone_id_map = array_combine($timezone_ids, $timezone_ids);
+
$form
->appendChild(
id(new AphrontFormFileControl())
->setLabel('Change Image')
->setName('profile')
->setCaption('Upload a 50x50px image.'))
->appendChild(
id(new AphrontFormMarkupControl())
->setValue('<hr />'))
+ ->appendChild(
+ id(new AphrontFormSelectControl())
+ ->setLabel('Timezone')
+ ->setName('timezone')
+ ->setOptions($timezone_id_map)
+ ->setValue($user->getTimezoneIdentifier()))
+ ->appendChild(
+ id(new AphrontFormMarkupControl())
+ ->setValue('<hr />'))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Save'));
}
$panel = new AphrontPanelView();
$panel->setHeader('Profile Settings');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->appendChild($form);
return $notice.$panel->render();
}
private function renderEmailForm(array $errors, $e_email) {
$request = $this->getRequest();
$user = $request->getUser();
$editable = $this->accountEditable;
$notice = null;
if (!$errors) {
if ($request->getStr('saved')) {
$notice = new AphrontErrorView();
$notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
$notice->setTitle('Changed Saved');
$notice->appendChild('<p>Your changes have been saved.</p>');
$notice = $notice->render();
}
} else {
$notice = new AphrontErrorView();
$notice->setTitle('Form Errors');
$notice->setErrors($errors);
$notice = $notice->render();
}
$form = new AphrontFormView();
$form
->setUser($user)
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Email')
->setName('email')
->setDisabled(!$editable)
->setCaption(
'Note: there is no email validation yet; double-check your '.
'typing.')
->setValue($user->getEmail())
->setError($e_email));
if ($editable) {
$form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Save'));
}
$panel = new AphrontPanelView();
$panel->setHeader('Email Settings');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->appendChild($form);
return $notice.$panel->render();
}
private function renderOAuthForm(PhabricatorOAuthProvider $provider) {
$request = $this->getRequest();
$user = $request->getUser();
$notice = null;
$provider_name = $provider->getProviderName();
$provider_key = $provider->getProviderKey();
$oauth_info = id(new PhabricatorUserOAuthInfo())->loadOneWhere(
'userID = %d AND oauthProvider = %s',
$user->getID(),
$provider->getProviderKey());
$form = new AphrontFormView();
$form
->setUser($user);
$forms = array();
$forms[] = $form;
if (!$oauth_info) {
$form
->appendChild(
'<p class="aphront-form-instructions">There is currently no '.
$provider_name.' account linked to your Phabricator account. You '.
'can link an account, which will allow you to use it to log into '.
'Phabricator.</p>');
switch ($provider_key) {
case PhabricatorOAuthProvider::PROVIDER_GITHUB:
$form->appendChild(
'<p class="aphront-form-instructions">Additionally, you must '.
'link your Github account before Phabricator can access any '.
'information about hosted repositories.</p>');
break;
}
$auth_uri = $provider->getAuthURI();
$client_id = $provider->getClientID();
$redirect_uri = $provider->getRedirectURI();
$form
->setAction($auth_uri)
->setMethod('GET')
->addHiddenInput('redirect_uri', $redirect_uri)
->addHiddenInput('client_id', $client_id)
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Link '.$provider_name." Account \xC2\xBB"));
} else {
$form
->appendChild(
'<p class="aphront-form-instructions">Your account is linked with '.
'a '.$provider_name.' account. You may use your '.$provider_name.' '.
'credentials to log into Phabricator.</p>')
->appendChild(
id(new AphrontFormStaticControl())
->setLabel($provider_name.' ID')
->setValue($oauth_info->getOAuthUID()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel($provider_name.' Name')
->setValue($oauth_info->getAccountName()))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel($provider_name.' URI')
->setValue($oauth_info->getAccountURI()));
if (!$provider->isProviderLinkPermanent()) {
$unlink = 'Unlink '.$provider_name.' Account';
$unlink_form = new AphrontFormView();
$unlink_form
->setUser($user)
->appendChild(
'<p class="aphront-form-instructions">You may unlink this account '.
'from your '.$provider_name.' account. This will prevent you from '.
'logging in with your '.$provider_name.' credentials.</p>')
->appendChild(
id(new AphrontFormSubmitControl())
->addCancelButton('/oauth/'.$provider_key.'/unlink/', $unlink));
$forms['Unlink Account'] = $unlink_form;
}
$expires = $oauth_info->getTokenExpires();
if ($expires) {
if ($expires <= time()) {
$expires = "Expired";
} else {
$expires = phabricator_format_timestamp($expires);
}
} else {
$expires = 'No Information Available';
}
$scope = $oauth_info->getTokenScope();
if (!$scope) {
$scope = 'No Information Available';
}
$status = $oauth_info->getTokenStatus();
$status = PhabricatorUserOAuthInfo::getReadableTokenStatus($status);
$token_form = new AphrontFormView();
$token_form
->setUser($user)
->appendChild(
'<p class="aphront-from-instructions">insert rap about tokens</p>')
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Token Status')
->setValue($status))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Expires')
->setValue($expires))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel('Scope')
->setValue($scope));
$forms['Account Token Information'] = $token_form;
}
$panel = new AphrontPanelView();
$panel->setHeader($provider_name.' Account Settings');
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
foreach ($forms as $name => $form) {
if ($name) {
$panel->appendChild('<br /><br /><h1>'.$name.'</h1>');
}
$panel->appendChild($form);
}
return $notice.$panel->render();
}
-}
\ No newline at end of file
+}
diff --git a/src/applications/people/controller/settings/__init__.php b/src/applications/people/controller/settings/__init__.php
index 0cc7f9d320..1a952ff9c4 100644
--- a/src/applications/people/controller/settings/__init__.php
+++ b/src/applications/people/controller/settings/__init__.php
@@ -1,38 +1,39 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/400');
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/auth/oauth/provider/base');
phutil_require_module('phabricator', 'applications/files/storage/file');
phutil_require_module('phabricator', 'applications/files/uri');
phutil_require_module('phabricator', 'applications/people/controller/base');
phutil_require_module('phabricator', 'applications/people/storage/user');
phutil_require_module('phabricator', 'applications/people/storage/useroauthinfo');
phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_module('phabricator', 'view/dialog');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/file');
phutil_require_module('phabricator', 'view/form/control/markup');
+phutil_require_module('phabricator', 'view/form/control/select');
phutil_require_module('phabricator', 'view/form/control/static');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/form/control/text');
phutil_require_module('phabricator', 'view/form/control/textarea');
phutil_require_module('phabricator', 'view/form/error');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phabricator', 'view/layout/sidenav');
phutil_require_module('phabricator', 'view/utils');
phutil_require_module('phutil', 'markup');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorUserSettingsController.php');
diff --git a/src/applications/people/storage/user/PhabricatorUser.php b/src/applications/people/storage/user/PhabricatorUser.php
index ab88cdc35e..c5cbe0a121 100644
--- a/src/applications/people/storage/user/PhabricatorUser.php
+++ b/src/applications/people/storage/user/PhabricatorUser.php
@@ -1,300 +1,301 @@
<?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 PhabricatorUser extends PhabricatorUserDAO {
const SESSION_TABLE = 'phabricator_session';
protected $phid;
protected $userName;
protected $realName;
protected $email;
protected $passwordSalt;
protected $passwordHash;
protected $profileImagePHID;
+ protected $timezoneIdentifier;
protected $consoleEnabled = 0;
protected $consoleVisible = 0;
protected $consoleTab = '';
protected $conduitCertificate;
protected $isSystemAgent = 0;
protected $isAdmin = 0;
protected $isDisabled = 0;
private $preferences = null;
public function getProfileImagePHID() {
return nonempty(
$this->profileImagePHID,
PhabricatorEnv::getEnvConfig('user.default-profile-image-phid'));
}
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorPHIDConstants::PHID_TYPE_USER);
}
public function setPassword($password) {
if (!$this->getPHID()) {
throw new Exception(
"You can not set a password for an unsaved user because their PHID ".
"is a salt component in the password hash.");
}
if (!strlen($password)) {
$this->setPasswordHash('');
} else {
$this->setPasswordSalt(md5(mt_rand()));
$hash = $this->hashPassword($password);
$this->setPasswordHash($hash);
}
return $this;
}
public function save() {
if (!$this->conduitCertificate) {
$this->conduitCertificate = $this->generateConduitCertificate();
}
return parent::save();
}
private function generateConduitCertificate() {
$entropy = Filesystem::readRandomBytes(256);
$entropy = base64_encode($entropy);
$entropy = substr($entropy, 0, 255);
return $entropy;
}
public function comparePassword($password) {
if (!strlen($password)) {
return false;
}
if (!strlen($this->getPasswordHash())) {
return false;
}
$password = $this->hashPassword($password);
return ($password === $this->getPasswordHash());
}
private function hashPassword($password) {
$password = $this->getUsername().
$password.
$this->getPHID().
$this->getPasswordSalt();
for ($ii = 0; $ii < 1000; $ii++) {
$password = md5($password);
}
return $password;
}
const CSRF_CYCLE_FREQUENCY = 3600;
const CSRF_TOKEN_LENGTH = 16;
const EMAIL_CYCLE_FREQUENCY = 86400;
const EMAIL_TOKEN_LENGTH = 24;
public function getCSRFToken($offset = 0) {
return $this->generateToken(
time() + (self::CSRF_CYCLE_FREQUENCY * $offset),
self::CSRF_CYCLE_FREQUENCY,
PhabricatorEnv::getEnvConfig('phabricator.csrf-key'),
self::CSRF_TOKEN_LENGTH);
}
public function validateCSRFToken($token) {
for ($ii = -1; $ii <= 1; $ii++) {
$valid = $this->getCSRFToken($ii);
if ($token == $valid) {
return true;
}
}
return false;
}
private function generateToken($epoch, $frequency, $key, $len) {
$time_block = floor($epoch / $frequency);
$vec = $this->getPHID().$this->passwordHash.$key.$time_block;
return substr(sha1($vec), 0, $len);
}
/**
* Issue a new session key to this user. Phabricator supports different
* types of sessions (like "web" and "conduit") and each session type may
* have multiple concurrent sessions (this allows a user to be logged in on
* multiple browsers at the same time, for instance).
*
* Note that this method is transport-agnostic and does not set cookies or
* issue other types of tokens, it ONLY generates a new session key.
*
* You can configure the maximum number of concurrent sessions for various
* session types in the Phabricator configuration.
*
* @param string Session type, like "web".
* @return string Newly generated session key.
*/
public function establishSession($session_type) {
$conn_w = $this->establishConnection('w');
if (strpos($session_type, '-') !== false) {
throw new Exception("Session type must not contain hyphen ('-')!");
}
// We allow multiple sessions of the same type, so when a caller requests
// a new session of type "web", we give them the first available session in
// "web-1", "web-2", ..., "web-N", up to some configurable limit. If none
// of these sessions is available, we overwrite the oldest session and
// reissue a new one in its place.
$session_limit = 1;
switch ($session_type) {
case 'web':
$session_limit = PhabricatorEnv::getEnvConfig('auth.sessions.web');
break;
case 'conduit':
$session_limit = PhabricatorEnv::getEnvConfig('auth.sessions.conduit');
break;
default:
throw new Exception("Unknown session type '{$session_type}'!");
}
$session_limit = (int)$session_limit;
if ($session_limit <= 0) {
throw new Exception(
"Session limit for '{$session_type}' must be at least 1!");
}
// Load all the currently active sessions.
$sessions = queryfx_all(
$conn_w,
'SELECT type, sessionStart FROM %T WHERE userPHID = %s AND type LIKE %>',
PhabricatorUser::SESSION_TABLE,
$this->getPHID(),
$session_type.'-');
// Choose which 'type' we'll actually establish, i.e. what number we're
// going to append to the basic session type. To do this, just check all
// the numbers sequentially until we find an available session.
$establish_type = null;
$sessions = ipull($sessions, null, 'type');
for ($ii = 1; $ii <= $session_limit; $ii++) {
if (empty($sessions[$session_type.'-'.$ii])) {
$establish_type = $session_type.'-'.$ii;
break;
}
}
// If we didn't find an available session, choose the oldest session and
// overwrite it.
if (!$establish_type) {
$sessions = isort($sessions, 'sessionStart');
$oldest = reset($sessions);
$establish_type = $oldest['type'];
}
// Consume entropy to generate a new session key, forestalling the eventual
// heat death of the universe.
$entropy = Filesystem::readRandomBytes(20);
$session_key = sha1($entropy);
queryfx(
$conn_w,
'INSERT INTO %T '.
'(userPHID, type, sessionKey, sessionStart)'.
' VALUES '.
'(%s, %s, %s, UNIX_TIMESTAMP()) '.
'ON DUPLICATE KEY UPDATE '.
'sessionKey = VALUES(sessionKey), '.
'sessionStart = VALUES(sessionStart)',
self::SESSION_TABLE,
$this->getPHID(),
$establish_type,
$session_key);
$log = PhabricatorUserLog::newLog(
$this,
$this,
PhabricatorUserLog::ACTION_LOGIN);
$log->setDetails(
array(
'session_type' => $session_type,
'session_issued' => $establish_type,
));
$log->setSession($session_key);
$log->save();
return $session_key;
}
private function generateEmailToken($offset = 0) {
return $this->generateToken(
time() + ($offset * self::EMAIL_CYCLE_FREQUENCY),
self::EMAIL_CYCLE_FREQUENCY,
PhabricatorEnv::getEnvConfig('phabricator.csrf-key').$this->getEmail(),
self::EMAIL_TOKEN_LENGTH);
}
public function validateEmailToken($token) {
for ($ii = -1; $ii <= 1; $ii++) {
$valid = $this->generateEmailToken($ii);
if ($token == $valid) {
return true;
}
}
return false;
}
public function getEmailLoginURI() {
$token = $this->generateEmailToken();
$uri = PhabricatorEnv::getProductionURI('/login/etoken/'.$token.'/');
$uri = new PhutilURI($uri);
return $uri->alter('email', $this->getEmail());
}
public function loadPreferences() {
if ($this->preferences) {
return $this->preferences;
}
$preferences = id(new PhabricatorUserPreferences())->loadOneWhere(
'userPHID = %s',
$this->getPHID());
if (!$preferences) {
$preferences = new PhabricatorUserPreferences();
$preferences->setUserPHID($this->getPHID());
$default_dict = array(
PhabricatorUserPreferences::PREFERENCE_TITLES => 'glyph',
PhabricatorUserPreferences::PREFERENCE_MONOSPACED => '');
$preferences->setPreferences($default_dict);
}
$this->preferences = $preferences;
return $preferences;
}
}
diff --git a/src/view/utils/viewutils.php b/src/view/utils/viewutils.php
index e0f3ec922e..3c18d95154 100644
--- a/src/view/utils/viewutils.php
+++ b/src/view/utils/viewutils.php
@@ -1,92 +1,110 @@
<?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.
*/
+function phabricator_date($epoch, $user) {
+ $zone = new DateTimeZone($user->getTimezoneIdentifier());
+ $date = new DateTime('@'.$epoch, $zone);
+ return $date->format('M j Y');
+}
+
+function phabricator_time($epoch, $user) {
+ $zone = new DateTimeZone($user->getTimezoneIdentifier());
+ $date = new DateTime('@'.$epoch, $zone);
+ return $date->format('g:i A');
+}
+
+function phabricator_datetime($epoch, $user) {
+ $zone = new DateTimeZone($user->getTimezoneIdentifier());
+ $date = new DateTime('@'.$epoch, $zone);
+ return $date->format('M j Y, g:i A');
+}
+
function phabricator_format_relative_time($duration) {
return phabricator_format_units_generic(
$duration,
array(60, 60, 24, 7),
array('s', 'm', 'h', 'd', 'w'),
$precision = 0);
}
function phabricator_format_timestamp($epoch) {
$difference = (time() - $epoch);
if ($difference < 0) {
$difference = -$difference;
$relative = 'from now';
} else {
$relative = 'ago';
}
if ($difference < 60 * 60 * 24) {
return phabricator_format_relative_time($difference).' '.$relative;
} else if (date('Y') == date('Y', $epoch)) {
return date('M j, g:i A', $epoch);
} else {
return date('F jS, Y', $epoch);
}
}
function phabricator_format_units_generic(
$n,
array $scales,
array $labels,
$precision = 0,
&$remainder = null) {
$is_negative = false;
if ($n < 0) {
$is_negative = true;
$n = abs($n);
}
$remainder = 0;
$accum = 1;
$scale = array_shift($scales);
$label = array_shift($labels);
while ($n > $scale && count($labels)) {
$remainder += ($n % $scale) * $accum;
$n /= $scale;
$accum *= $scale;
$label = array_shift($labels);
if (!count($scales)) {
break;
}
$scale = array_shift($scales);
}
if ($is_negative) {
$n = -$n;
$remainder = -$remainder;
}
if ($precision) {
$num_string = number_format($n, $precision);
} else {
$num_string = (int)floor($n);
}
if ($label) {
$num_string .= ' '.$label;
}
return $num_string;
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 16:01 (2 w, 6 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1126280
Default Alt Text
(146 KB)

Event Timeline