diff --git a/.gitignore b/.gitignore index 41c318a73..d176eb3a0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,29 @@ .DS_Store ._* /webroot/rsrc/custom .#* *# *~ *.swp # NetBeans project files /nbproject/ # Arcanist scratch directory /.arc # Diviner /docs/ /.divinercache # libphutil /src/.phutil_module_cache # Configuration /conf/custom/* /conf/local/local.json /conf/local/ENVIRONMENT /conf/local/VERSION + +# Impact Font +/resources/font/impact.ttf diff --git a/conf/default.conf.php b/conf/default.conf.php index 6cc166c32..a9e4cff5a 100644 --- a/conf/default.conf.php +++ b/conf/default.conf.php @@ -1,1347 +1,1336 @@ null, // If you have multiple environments, provide the production environment URI // here so that emails, etc., generated in development/sandbox environments // contain the right links. 'phabricator.production-uri' => null, // -- IMPORTANT! Security! -------------------------------------------------- // // IMPORTANT: By default, Phabricator serves files from the same domain the // application lives on. This is convenient but not secure: it creates a large // class of vulnerabilities which can not be generally mitigated. // // To avoid this, you should configure a second domain in the same way you // have the primary domain configured (e.g., point it at the same machine and // set up the same vhost rules) and provide it here. For instance, if your // primary install is on "http://www.phabricator-example.com/", you could // configure "http://www.phabricator-files.com/" and specify the entire // domain (with protocol) here. This will enforce that files are // served only from the alternate domain. Ideally, you should use a // completely separate domain name rather than just a different subdomain. // // It is STRONGLY RECOMMENDED that you configure this. Your install is NOT // SECURE unless you do so. 'security.alternate-file-domain' => null, // Default key for HMAC digests where the key is not important (i.e., the // hash itself is secret). You can change this if you want (to any other // string), but doing so will break existing sessions and CSRF tokens. 'security.hmac-key' => '[D\t~Y7eNmnQGJ;rnH6aF;m2!vJ8@v8C=Cs:aQS\.Qw', // If the web server responds to both HTTP and HTTPS requests but you want // users to connect with only HTTPS, you can set this to true to make // Phabricator redirect HTTP requests to HTTPS. // // Normally, you should just configure your server not to accept HTTP traffic, // but this setting may be useful if you originally used HTTP and have now // switched to HTTPS but don't want to break old links, or if your webserver // sits behind a load balancer which terminates HTTPS connections and you // can not reasonably configure more granular behavior there. // // NOTE: Phabricator determines if a request is HTTPS or not by examining the // PHP $_SERVER['HTTPS'] variable. If you run Apache/mod_php this will // probably be set correctly for you automatically, but if you run Phabricator // as CGI/FCGI (e.g., through nginx or lighttpd), you need to configure your // web server so that it passes the value correctly based on the connection // type. Alternatively, you can add a PHP snippet to the top of this // configuration file to directly set $_SERVER['HTTPS'] to the correct value. 'security.require-https' => false, // -- Internationalization -------------------------------------------------- // // This allows customizing texts used in Phabricator. The class must extend // PhabricatorTranslation. 'translation.provider' => 'PhabricatorEnglishTranslation', // You can use 'translation.override' if you don't want to create a full // translation to give users an option for switching to it and you just want // to override some strings in the default translation. 'translation.override' => array(), // -- Access Policies ------------------------------------------------------- // // Phabricator allows you to set the visibility of objects (like repositories // and source code) to "Public", which means anyone on the internet can see // them, even without being logged in. This is great for open source, but // some installs may never want to make anything public, so this policy is // disabled by default. You can enable it here, which will let you set the // policy for objects to "Public". With this option disabled, the most open // policy is "All Users", which means users must be logged in to view things. 'policy.allow-public' => false, // -- Logging --------------------------------------------------------------- // // To enable the Phabricator access log, specify a path here. The Phabricator // access log can provide more detailed information about Phabricator access // than normal HTTP access logs (for instance, it can show logged-in users, // controllers, and other application data). If not set, no log will be // written. // // Make sure the PHP process can write to the log! 'log.access.path' => null, // Format for the access log. If not set, the default format will be used: // // "[%D]\t%h\t%u\t%M\t%C\t%m\t%U\t%c\t%T" // // Available variables are: // // - %c The HTTP response code. // - %C The controller which handled the request. // - %D The request date. // - %e Epoch timestamp. // - %h The webserver's host name. // - %p The PID of the server process. // - %R The HTTP referrer. // - %r The remote IP. // - %T The request duration, in microseconds. // - %U The request path. // - %u The logged-in user, if one is logged in. // - %M The HTTP method. // - %m For conduit, the Conduit method which was invoked. // // If a variable isn't available (for example, %m appears in the file format // but the request is not a Conduit request), it will be rendered as "-". // // Note that the default format is subject to change in the future, so if you // rely on the log's format, specify it explicitly. 'log.access.format' => null, // -- DarkConsole ----------------------------------------------------------- // // DarkConsole is a administrative debugging/profiling tool built into // Phabricator. You can leave it disabled unless you're developing against // Phabricator. // Determines whether or not DarkConsole is available. DarkConsole exposes // some data like queries and stack traces, so you should be careful about // turning it on in production (although users can not normally see it, even // if the deployment configuration enables it). 'darkconsole.enabled' => false, // Always enable DarkConsole, even for logged out users. This potentially // exposes sensitive information to users, so make sure untrusted users can // not access an install running in this mode. You should definitely leave // this off in production. It is only really useful for using DarkConsole // utilities to debug or profile logged-out pages. You must set // 'darkconsole.enabled' to use this option. 'darkconsole.always-on' => false, // Map of additional configuration values to lock. 'config.lock' => array(), // Map of additional configuration values to hide. 'config.hide' => array(), // Map of additional configuration values to mask. 'config.mask' => array(), // -- MySQL --------------------------------------------------------------- // // Class providing database configuration. It must implement // DatabaseConfigurationProvider. 'mysql.configuration-provider' => 'DefaultDatabaseConfigurationProvider', // The username to use when connecting to MySQL. 'mysql.user' => 'root', // The password to use when connecting to MySQL. 'mysql.pass' => '', // The MySQL server to connect to. If you want to connect to a different // port than the default (which is 3306), specify it in the hostname // (e.g., db.example.com:1234). 'mysql.host' => 'localhost', // Phabricator supports PHP extensions MySQL and MySQLi. It is possible to // implement also other access mechanism (e.g. PDO_MySQL). The class must // extend AphrontMySQLDatabaseConnectionBase. 'mysql.implementation' => 'AphrontMySQLDatabaseConnection', // -- Notifications --------------------------------------------------------- // // Set this to true to enable real-time notifications. You must also run a // notification server for this to work. Consult the documentation in // "Notifications User Guide: Setup and Configuration" for instructions. 'notification.enabled' => false, // Client port for the realtime server to listen on, and for realtime clients // to connect to. Use "localhost" if you are running the notification server // on the same host as the web server. 'notification.client-uri' => 'http://localhost:22280/', // URI and port for the notification root server. 'notification.server-uri' => 'http://localhost:22281/', // The server must be started as root so it can bind to privileged ports, but // if you specify a user here it will drop permissions after binding. 'notification.user' => null, // Location where the server should log to. 'notification.log' => '/var/log/aphlict.log', // PID file to use. 'notification.pidfile' => '/var/run/aphlict.pid', // Enable this option to get additional debug output in the browser. 'notification.debug' => false, // -- Email ----------------------------------------------------------------- // // Some Phabricator tools send email notifications, e.g. when Differential // revisions are updated or Maniphest tasks are changed. These options allow // you to configure how email is delivered. // You can test your mail setup by going to "MetaMTA" in the web interface, // clicking "Send New Message", and then composing a message. // Default address to send mail "From". 'metamta.default-address' => 'noreply@example.com', // Domain used to generate Message-IDs. 'metamta.domain' => 'example.com', // When a message is sent to multiple recipients (for example, several // reviewers on a code review), Phabricator can either deliver one email to // everyone (e.g., "To: alincoln, usgrant, htaft") or separate emails to each // user (e.g., "To: alincoln", "To: usgrant", "To: htaft"). The major // advantages and disadvantages of each approach are: // // - One mail to everyone: // - Recipients can see To/Cc at a glance. // - If you use mailing lists, you won't get duplicate mail if you're // a normal recipient and also Cc'd on a mailing list. // - Getting threading to work properly is harder, and probably requires // making mail less useful by turning off options. // - Sometimes people will "Reply All" and everyone will get two mails, // one from the user and one from Phabricator turning their mail into // a comment. // - Not supported with a private reply-to address. // - Mails are sent in the server default translation. // - One mail to each user: // - Recipients need to look in the mail body to see To/Cc. // - If you use mailing lists, recipients may sometimes get duplicate // mail. // - Getting threading to work properly is easier, and threading settings // can be customzied by each user. // - "Reply All" no longer spams all other users. // - Required if private reply-to addresses are configured. // - Mails are sent in the language of user preference. // // In the code, splitting one outbound email into one-per-recipient is // sometimes referred to as "multiplexing". 'metamta.one-mail-per-recipient' => true, // When sending a message that has no To recipient (i.e. all recipients // are CC'd, for example when multiplexing mail), set the To field to the // following value. If no value is set, messages with no To will have // their CCs upgraded to To. 'metamta.placeholder-to-recipient' => null, // When a user takes an action which generates an email notification (like // commenting on a Differential revision), Phabricator can either send that // mail "From" the user's email address (like "alincoln@logcabin.com") or // "From" the 'metamta.default-address' address. The user experience is // generally better if Phabricator uses the user's real address as the "From" // since the messages are easier to organize when they appear in mail clients, // but this will only work if the server is authorized to send email on behalf // of the "From" domain. Practically, this means: // - If you are doing an install for Example Corp and all the users will // have corporate @corp.example.com addresses and any hosts Phabricator // is running on are authorized to send email from corp.example.com, // you can enable this to make the user experience a little better. // - If you are doing an install for an open source project and your // users will be registering via Facebook and using personal email // addresses, you MUST NOT enable this or virtually all of your outgoing // email will vanish into SFP blackholes. // - If your install is anything else, you're much safer leaving this // off since the risk in turning it on is that your outgoing mail will // mostly never arrive. 'metamta.can-send-as-user' => false, // Adapter class to use to transmit mail to the MTA. The default uses // PHPMailerLite, which will invoke "sendmail". This is appropriate // if sendmail actually works on your host, but if you haven't configured mail // it may not be so great. A number of other mailers are available (e.g., SES, // SendGrid, SMTP, custom mailers), consult "Configuring Outbound Email" in // the documentation for details. 'metamta.mail-adapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter', // When email is sent, try to hand it off to the MTA immediately instead of // queueing it for delivery by the daemons. If you are running the Phabricator // daemons with "phd start", you should disable this to provide a (sometimes // substantial) performance boost. It's on by default to make setup and // configuration a little easier. 'metamta.send-immediately' => true, // When email is sent, what format should Phabricator use for user's // email addresses? Valid values are: // - 'short' - 'gwashington ' // - 'real' - 'George Washington ' // - 'full' - 'gwashington (George Washington) ' // The default is 'full'. 'metamta.user-address-format' => 'full', // If you're using PHPMailer to send email, provide the mailer and options // here. PHPMailer is much more enormous than PHPMailerLite, and provides more // mailers and greater enormity. You need it when you want to use SMTP // instead of sendmail as the mailer. 'phpmailer.mailer' => 'smtp', 'phpmailer.smtp-host' => '', 'phpmailer.smtp-port' => 25, // When using PHPMailer with SMTP, you can set this to one of "tls" or "ssl" // to use TLS or SSL. Leave it blank for vanilla SMTP. If you're sending // via Gmail, set it to "ssl". 'phpmailer.smtp-protocol' => '', // Set following if your smtp server requires authentication. 'phpmailer.smtp-user' => null, 'phpmailer.smtp-password' => null, // If you're using Amazon SES to send email, provide your AWS access key // and AWS secret key here. To set up Amazon SES with Phabricator, you need // to: // - Make sure 'metamta.mail-adapter' is set to: // "PhabricatorMailImplementationAmazonSESAdapter" // - Make sure 'metamta.can-send-as-user' is false. // - Make sure 'metamta.default-address' is configured to something sensible. // - Make sure 'metamta.default-address' is a validated SES "From" address. 'amazon-ses.access-key' => null, 'amazon-ses.secret-key' => null, // If you're using Sendgrid to send email, provide your access credentials // here. This will use the REST API. You can also use Sendgrid as a normal // SMTP service. 'sendgrid.api-user' => null, 'sendgrid.api-key' => null, // You can configure a reply handler domain so that email sent from Maniphest // will have a special "Reply To" address like "T123+82+af19f@example.com" // that allows recipients to reply by email and interact with tasks. For // instructions on configurating reply handlers, see the article // "Configuring Inbound Email" in the Phabricator documentation. By default, // this is set to 'null' and Phabricator will use a generic 'noreply@' address // or the address of the acting user instead of a special reply handler // address (see 'metamta.default-address'). If you set a domain here, // Phabricator will begin generating private reply handler addresses. See // also 'metamta.maniphest.reply-handler' to further configure behavior. // This key should be set to the domain part after the @, like "example.com". 'metamta.maniphest.reply-handler-domain' => null, // You can follow the instructions in "Configuring Inbound Email" in the // Phabricator documentation and set 'metamta.maniphest.reply-handler-domain' // to support updating Maniphest tasks by email. If you want more advanced // customization than this provides, you can override the reply handler // class with an implementation of your own. This will allow you to do things // like have a single public reply handler or change how private reply // handlers are generated and validated. // // This key should be set to a loadable subclass of // PhabricatorMailReplyHandler. 'metamta.maniphest.reply-handler' => 'ManiphestReplyHandler', // If you don't want phabricator to take up an entire domain // (or subdomain for that matter), you can use this and set a common // prefix for mail sent by phabricator. It will make use of the fact that // a mail-address such as phabricator+D123+1hjk213h@example.com will be // delivered to the phabricator users mailbox. // Set this to the left part of the email address and it well get // prepended to all outgoing mail. If you want to use e.g. // 'phabricator@example.com' this should be set to 'phabricator'. 'metamta.single-reply-handler-prefix' => null, // Prefix prepended to mail sent by Maniphest. You can change this to // distinguish between testing and development installs, for example. 'metamta.maniphest.subject-prefix' => '[Maniphest]', // See 'metamta.maniphest.reply-handler-domain'. This does the same thing, but // affects Pholio. 'metamta.pholio.reply-handler-domain' => null, // Prefix prepended to mail sent by Pholio. 'metamta.pholio.subject-prefix' => '[Pholio]', // See 'metamta.maniphest.reply-handler-domain'. This does the same thing, but // affects Macro. 'metamta.macro.reply-handler-domain' => null, // Prefix prepended to mail sent by Macro. 'metamta.macro.subject-prefix' => '[Macro]', // See 'metamta.maniphest.reply-handler-domain'. This does the same thing, // but allows email replies via Differential. 'metamta.differential.reply-handler-domain' => null, // See 'metamta.maniphest.reply-handler'. This does the same thing, but // affects Differential. 'metamta.differential.reply-handler' => 'DifferentialReplyHandler', // Prefix prepended to mail sent by Differential. 'metamta.differential.subject-prefix' => '[Differential]', // Set this to true if you want patches to be attached to mail from // Differential. This won't work if you are using SendGrid as your mail // adapter. 'metamta.differential.attach-patches' => false, // To include patches in email bodies, set this to a positive integer. Patches // will be inlined if they are at most that many lines. For instance, a value // of 100 means "inline patches if they are no longer than 100 lines". By // default, patches are not inlined. 'metamta.differential.inline-patches' => 0, // If you enable either of the options above, you can choose what format // patches are sent in. Valid options are 'unified' (like diff -u) or 'git'. 'metamta.differential.patch-format' => 'unified', // Enables a different format for comments in differential emails. // Differential will create unified diffs around the comment, which // will give enough context for people who are only viewing the // reviews in email to understand what is going on. The context will // be created based on the range of the comment. 'metamta.differential.unified-comment-context' => false, // Prefix prepended to mail sent by Diffusion. 'metamta.diffusion.subject-prefix' => '[Diffusion]', // See 'metamta.maniphest.reply-handler-domain'. This does the same thing, // but allows email replies via Diffusion. 'metamta.diffusion.reply-handler-domain' => null, // See 'metamta.maniphest.reply-handler'. This does the same thing, but // affects Diffusion. 'metamta.diffusion.reply-handler' => 'PhabricatorAuditReplyHandler', // Set this to true if you want patches to be attached to commit notifications // from Diffusion. This won't work with SendGrid. 'metamta.diffusion.attach-patches' => false, // To include patches in Diffusion email bodies, set this to a positive // integer. Patches will be inlined if they are at most that many lines. // By default, patches are not inlined. 'metamta.diffusion.inline-patches' => 0, // If you've enabled attached patches or inline patches for commit emails, you // can establish a hard byte limit on their size. You should generally set // reasonable byte and time limits (defaults are 1MB and 60 seconds) to avoid // sending ridiculously enormous email for changes like "importing an external // library" or "accidentally committed this full-length movie as text". 'metamta.diffusion.byte-limit' => 1024 * 1024, // If you've enabled attached patches or inline patches for commit emails, you // can establish a hard time limit on generating them. 'metamta.diffusion.time-limit' => 60, // Prefix prepended to mail sent by Package. 'metamta.package.subject-prefix' => '[Package]', // See 'metamta.maniphest.reply-handler'. This does similar thing for package // except that it only supports sending out mail and doesn't handle incoming // email. 'metamta.package.reply-handler' => 'OwnersPackageReplyHandler', // By default, Phabricator generates unique reply-to addresses and sends a // separate email to each recipient when you enable reply handling. This is // more secure than using "From" to establish user identity, but can mean // users may receive multiple emails when they are on mailing lists. Instead, // you can use a single, non-unique reply to address and authenticate users // based on the "From" address by setting this to 'true'. This trades away // a little bit of security for convenience, but it's reasonable in many // installs. Object interactions are still protected using hashes in the // single public email address, so objects can not be replied to blindly. 'metamta.public-replies' => false, // You can configure an email address like "bugs@phabricator.example.com" // which will automatically create Maniphest tasks when users send email // to it. This relies on the "From" address to authenticate users, so it is // is not completely secure. To set this up, enter a complete email // address like "bugs@phabricator.example.com" and then configure mail to // that address so it routed to Phabricator (if you've already configured // reply handlers, you're probably already done). See "Configuring Inbound // Email" in the documentation for more information. 'metamta.maniphest.public-create-email' => null, // If you enable 'metamta.public-replies', Phabricator uses "From" to // authenticate users. You can additionally enable this setting to try to // authenticate with 'Reply-To'. Note that this is completely spoofable and // insecure (any user can set any 'Reply-To' address) but depending on the // nature of your install or other deliverability conditions this might be // okay. Generally, you can't do much more by spoofing Reply-To than be // annoying (you can write but not read content). But, you know, this is // still **COMPLETELY INSECURE**. 'metamta.insecure-auth-with-reply-to' => false, // If you enable 'metamta.maniphest.public-create-email' and create an // email address like "bugs@phabricator.example.com", it will default to // rejecting mail which doesn't come from a known user. However, you might // want to let anyone send email to this address; to do so, set a default // author here (a Phabricator username). A typical use of this might be to // create a "System Agent" user called "bugs" and use that name here. If you // specify a valid username, mail will always be accepted and used to create // a task, even if the sender is not a system user. The original email // address will be stored in an 'From Email' field on the task. 'metamta.maniphest.default-public-author' => null, // You can disable the Herald hints in email if users prefer smaller messages. // These are the links under the headers "MANAGE HERALD RULES" and // "WHY DID I GET THIS EMAIL?". If you set this to true, they will not appear // in any mail. Users can still navigate to the links via the web interface. 'metamta.herald.show-hints' => true, // You can disable the hints under "REPLY HANDLER ACTIONS" if users prefer // smaller messages. The actions themselves will still work properly. 'metamta.reply.show-hints' => true, // You can disable the "To:" and "Cc:" footers in mail if users prefer // smaller messages. 'metamta.recipients.show-hints' => true, // If this option is enabled, Phabricator will add a "Precedence: bulk" // header to transactional mail (e.g., Differential, Maniphest and Herald // notifications). This may improve the behavior of some auto-responder // software and prevent it from replying. However, it may also cause // deliverability issues -- notably, you currently can not send this header // via Amazon SES, and enabling this option with SES will prevent delivery // of any affected mail. 'metamta.precedence-bulk' => false, // Mail.app on OS X Lion won't respect threading headers unless the subject // is prefixed with "Re:". If you enable this option, Phabricator will add // "Re:" to the subject line of all mail which is expected to thread. If // you've set 'metamta.one-mail-per-recipient', users can override this // setting in their preferences. 'metamta.re-prefix' => false, // If true, allow MetaMTA to change mail subjects to put text like // '[Accepted]' and '[Commented]' in them. This makes subjects more useful, // but might break threading on some clients. If you've set // 'metamta.one-mail-per-recipient', users can override this setting in their // preferences. 'metamta.vary-subjects' => true, // -- Auth ------------------------------------------------------------------ // // Can users login with a username/password, or by following the link from // a password reset email? You can disable this and configure one or more // OAuth providers instead. 'auth.password-auth-enabled' => true, // Maximum number of simultaneous web sessions each user is permitted to have. // Setting this to "1" will prevent a user from logging in on more than one // browser at the same time. 'auth.sessions.web' => 5, // Maximum number of simultaneous Conduit sessions each user is permitted // to have. 'auth.sessions.conduit' => 5, // Set this true to enable the Settings -> SSH Public Keys panel, which will // allow users to associated SSH public keys with their accounts. This is only // really useful if you're setting up services over SSH and want to use // Phabricator for authentication; in most situations you can leave this // disabled. 'auth.sshkeys.enabled' => false, // If true, email addresses must be verified (by clicking a link in an // email) before a user can login. By default, verification is optional // unless 'auth.email-domains' is nonempty (see below). 'auth.require-email-verification' => false, // You can restrict allowed email addresses to certain domains (like // "yourcompany.com") by setting a list of allowed domains here. Users will // only be allowed to register using email addresses at one of the domains, // and will only be able to add new email addresses for these domains. If // you configure this, it implies 'auth.require-email-verification'. // // To configure email domains, set a list of domains like this: // // array( // 'yourcompany.com', // 'yourcompany.co.uk', // ) // // You should omit the "@" from domains. Note that the domain must match // exactly. If you allow "yourcompany.com", that permits "joe@yourcompany.com" // but rejects "joe@mail.yourcompany.com". 'auth.email-domains' => array(), // You can provide an arbitrary block of HTML here, which will appear on the // login screen. Normally, you'd use this to provide login or registration // instructions to users. 'auth.login-message' => null, // -- Accounts -------------------------------------------------------------- // // Is basic account information (email, real name, profile picture) editable? // If you set up Phabricator to automatically synchronize account information // from some other authoritative system, you can disable this to ensure // information remains consistent across both systems. 'account.editable' => true, // When users set or reset a password, it must have at least this many // characters. 'account.minimum-password-length' => 8, // -- Facebook OAuth -------------------------------------------------------- // // Can users use Facebook credentials to login to Phabricator? 'facebook.auth-enabled' => false, // Can users use Facebook credentials to create new Phabricator accounts? 'facebook.registration-enabled' => true, // Are Facebook accounts permanently linked to Phabricator accounts, or can // the user unlink them? 'facebook.auth-permanent' => false, // The Facebook "Application ID" to use for Facebook API access. 'facebook.application-id' => null, // The Facebook "Application Secret" to use for Facebook API access. 'facebook.application-secret' => null, // Should Phabricator reject requests made by users with // Secure Browsing disabled? 'facebook.require-https-auth' => false, // -- GitHub OAuth ---------------------------------------------------------- // // Can users use GitHub credentials to login to Phabricator? 'github.auth-enabled' => false, // Can users use GitHub credentials to create new Phabricator accounts? 'github.registration-enabled' => true, // Are GitHub accounts permanently linked to Phabricator accounts, or can // the user unlink them? 'github.auth-permanent' => false, // The GitHub "Client ID" to use for GitHub API access. 'github.application-id' => null, // The GitHub "Secret" to use for GitHub API access. 'github.application-secret' => null, // -- Google OAuth ---------------------------------------------------------- // // Can users use Google credentials to login to Phabricator? 'google.auth-enabled' => false, // Can users use Google credentials to create new Phabricator accounts? 'google.registration-enabled' => true, // Are Google accounts permanently linked to Phabricator accounts, or can // the user unlink them? 'google.auth-permanent' => false, // The Google "Client ID" to use for Google API access. 'google.application-id' => null, // The Google "Client Secret" to use for Google API access. 'google.application-secret' => null, // -- LDAP Auth ----------------------------------------------------- // // Enable ldap auth 'ldap.auth-enabled' => false, // The LDAP server hostname 'ldap.hostname' => null, // The LDAP server port 'ldap.port' => 389, // The LDAP base domain name 'ldap.base_dn' => null, // The attribute to be regarded as 'username'. Has to be unique 'ldap.search_attribute' => null, // Perform a search to find a user // Many LDAP installations do not have the username in the dn, if this is // true for you set this to true and configure the username_attribute below 'ldap.search-first' => false, // The attribute to search for if you have to search for a user 'ldap.username-attribute' => null, // The attribute(s) to be regarded as 'real name'. // If more then one attribute is supplied the values of the attributes in // the array will be joined 'ldap.real_name_attributes' => array(), // A domain name to use when authenticating against Active Directory // (e.g. 'example.com') 'ldap.activedirectory_domain' => null, // The LDAP version 'ldap.version' => 3, // LDAP Referrals Option // Whether referrals should be followed by the client // Should be set to 0 if you use Windows 2003 AD 'ldap.referrals' => true, // The anonymous user name to use before searching a user. // Many LDAP installations require login even before searching a user, set // this option to enable it. 'ldap.anonymous-user-name' => null, // The password of the LDAP anonymous user. 'ldap.anonymous-user-password' => null, // Whether to use STARTTLS 'ldap.start-tls' => false, // -- Disqus OAuth ---------------------------------------------------------- // // Can users use Disqus credentials to login to Phabricator? 'disqus.auth-enabled' => false, // Can users use Disqus credentials to create new Phabricator accounts? 'disqus.registration-enabled' => true, // Are Disqus accounts permanently linked to Phabricator accounts, or can // the user unlink them? 'disqus.auth-permanent' => false, // The Disqus "Client ID" to use for Disqus API access. 'disqus.application-id' => null, // The Disqus "Client Secret" to use for Disqus API access. 'disqus.application-secret' => null, // -- Phabricator OAuth ----------------------------------------------------- // // Meta-town -- Phabricator is itself an OAuth Provider // TODO -- T887 -- make this support multiple Phabricator instances! // The URI of the Phabricator instance to use as an OAuth server. 'phabricator.oauth-uri' => null, // Can users use Phabricator credentials to login to Phabricator? 'phabricator.auth-enabled' => false, // Can users use Phabricator credentials to create new Phabricator accounts? 'phabricator.registration-enabled' => true, // Are Phabricator accounts permanently linked to Phabricator accounts, or can // the user unlink them? 'phabricator.auth-permanent' => false, // The Phabricator "Client ID" to use for Phabricator API access. 'phabricator.application-id' => null, // The Phabricator "Client Secret" to use for Phabricator API access. 'phabricator.application-secret' => null, // -- Recaptcha ------------------------------------------------------------- // // Is Recaptcha enabled? If disabled, captchas will not appear. You should // enable Recaptcha if your install is public-facing, as it hinders // brute-force attacks. 'recaptcha.enabled' => false, // Your Recaptcha public key, obtained from Recaptcha. 'recaptcha.public-key' => null, // Your Recaptcha private key, obtained from Recaptcha. 'recaptcha.private-key' => null, // -- Misc ------------------------------------------------------------------ // // This is hashed with other inputs to generate CSRF tokens. If you want, you // can change it to some other string which is unique to your install. This // will make your install more secure in a vague, mostly theoretical way. But // it will take you like 3 seconds of mashing on your keyboard to set it up so // you might as well. 'phabricator.csrf-key' => '0b7ec0592e0a2829d8b71df2fa269b2c6172eca3', // This is hashed with other inputs to generate mail tokens. If you want, you // can change it to some other string which is unique to your install. In // particular, you will want to do this if you accidentally send a bunch of // mail somewhere you shouldn't have, to invalidate all old reply-to // addresses. 'phabricator.mail-key' => '5ce3e7e8787f6e40dfae861da315a5cdf1018f12', // PHP requires that you set a timezone in your php.ini before using date // functions, or it will emit a warning. If this isn't possible (for instance, // because you are using HPHP) you can set some valid constant for // date_default_timezone_set() here and Phabricator will set it on your // behalf, silencing the warning. 'phabricator.timezone' => null, - // When unhandled exceptions occur, stack traces are hidden by default. - // You can enable traces for development to make it easier to debug problems. - 'phabricator.show-stack-traces' => false, - - // Shows an error callout if a page generated PHP errors, warnings or notices. - // This makes it harder to miss problems while developing Phabricator. - 'phabricator.show-error-callout' => false, + // Show stack traces when unhandled exceptions occur, force reloading of + // static resources (skipping the cache), show an error callout if a page + // generated PHP errors, warnings, or notices, force disk reads when + // reloading. This option should not be enabled in production. + 'phabricator.developer-mode' => false, // When users write comments which have URIs, they'll be automatically linked // if the protocol appears in this set. This whitelist is primarily to prevent // security issues like javascript:// URIs. 'uri.allowed-protocols' => array( 'http' => true, 'https' => true, ), // Tokenizers are UI controls which let the user select other users, email // addresses, project names, etc., by typing the first few letters and having // the control autocomplete from a list. They can load their data in two ways: // either in a big chunk up front, or as the user types. By default, the data // is loaded in a big chunk. This is simpler and performs better for small // datasets. However, if you have a very large number of users or projects, // (in the ballpark of more than a thousand), loading all that data may become // slow enough that it's worthwhile to query on demand instead. This makes // the typeahead slightly less responsive but overall performance will be much // better if you have a ton of stuff. You can figure out which setting is // best for your install by changing this setting and then playing with a // user tokenizer (like the user selectors in Maniphest or Differential) and // seeing which setting loads faster and feels better. 'tokenizer.ondemand' => false, // By default, Phabricator includes some silly nonsense in the UI, such as // a submit button called "Clowncopterize" in Differential and a call to // "Leap Into Action". If you'd prefer more traditional UI strings like // "Submit", you can set this flag to disable most of the jokes and easter // eggs. 'phabricator.serious-business' => false, // Should Phabricator show beta applications on the homepage 'phabricator.show-beta-applications' => false, // Contains a list of uninstalled applications 'phabricator.uninstalled-applications' => array(), // -- Files ----------------------------------------------------------------- // // Lists which uploaded file types may be viewed in the browser. If a file // has a mime type which does not appear in this list, it will always be // downloaded instead of displayed. This is mainly a usability // consideration, since browsers tend to freak out when viewing enormous // binary files. // // The keys in this array are viewable mime types; the values are the mime // types they will be delivered as when they are viewed in the browser. // // IMPORTANT: Configure 'security.alternate-file-domain' above! Your install // is NOT safe if it is left unconfigured. 'files.viewable-mime-types' => array( 'image/jpeg' => 'image/jpeg', 'image/jpg' => 'image/jpg', 'image/png' => 'image/png', 'image/gif' => 'image/gif', 'text/plain' => 'text/plain; charset=utf-8', 'text/x-diff' => 'text/plain; charset=utf-8', // ".ico" favicon files, which have mime type diversity. See: // http://en.wikipedia.org/wiki/ICO_(file_format)#MIME_type 'image/x-ico' => 'image/x-icon', 'image/x-icon' => 'image/x-icon', 'image/vnd.microsoft.icon' => 'image/x-icon', ), // List of mime types which can be used as the source for an tag. // This should be a subset of 'files.viewable-mime-types' and exclude files // like text. 'files.image-mime-types' => array( 'image/jpeg' => true, 'image/jpg' => true, 'image/png' => true, 'image/gif' => true, 'image/x-ico' => true, 'image/x-icon' => true, 'image/vnd.microsoft.icon' => true, ), // -- Storage --------------------------------------------------------------- // // Phabricator allows users to upload files, and can keep them in various // storage engines. This section allows you to configure which engines // Phabricator will use, and how it will use them. // The largest filesize Phabricator will store in the MySQL BLOB storage // engine, which just uses a database table to store files. While this isn't a // best practice, it's really easy to set up. Set this to 0 to disable use of // the MySQL blob engine. 'storage.mysql-engine.max-size' => 1000000, // Phabricator provides a local disk storage engine, which just writes files // to some directory on local disk. The webserver must have read/write // permissions on this directory. This is straightforward and suitable for // most installs, but will not scale past one web frontend unless the path // is actually an NFS mount, since you'll end up with some of the files // written to each web frontend and no way for them to share. To use the // local disk storage engine, specify the path to a directory here. To // disable it, specify null. 'storage.local-disk.path' => null, // If you want to store files in Amazon S3, specify an AWS access and secret // key here and a bucket name below. 'amazon-s3.access-key' => null, 'amazon-s3.secret-key' => null, // To use a custom endpoint, specify it here. Normally, you do not need to // configure this. 'amazon-s3.endpoint' => null, // Set this to a valid Amazon S3 bucket to store files there. You must also // configure S3 access keys above. 'storage.s3.bucket' => null, // Phabricator uses a storage engine selector to choose which storage engine // to use when writing file data. If you add new storage engines or want to // provide very custom rules (e.g., write images to one storage engine and // other files to a different one), you can provide an alternate // implementation here. The default engine will use choose MySQL, Local Disk, // and S3, in that order, if they have valid configurations above and a file // fits within configured limits. 'storage.engine-selector' => 'PhabricatorDefaultFileStorageEngineSelector', // Set the size of the largest file a user may upload. This is used to render // text like "Maximum file size: 10MB" on interfaces where users can upload // files, and files larger than this size will be rejected. // // Specify this limit in bytes, or using a "K", "M", or "G" suffix. // // NOTE: Setting this to a large size is NOT sufficient to allow users to // upload large files. You must also configure a number of other settings. To // configure file upload limits, consult the article "Configuring File Upload // Limits" in the documentation. Once you've configured some limit across all // levels of the server, you can set this limit to an appropriate value and // the UI will then reflect the actual configured limit. 'storage.upload-size-limit' => null, // Phabricator puts databases in a namespace, which defualts to "phabricator" // -- for instance, the Differential database is named // "phabricator_differential" by default. You can change this namespace if you // want. Normally, you should not do this unless you are developing // Phabricator and using namespaces to separate multiple sandbox datasets. 'storage.default-namespace' => 'phabricator', // -- Search ---------------------------------------------------------------- // // Phabricator supports Elastic Search; to use it, specify a host like // 'http://elastic.example.com:9200/' here. 'search.elastic.host' => null, // Phabricator uses a search engine selector to choose which search engine // to use when indexing and reconstructing documents, and when executing // queries. You can override the engine selector to provide a new selector // class which can select some custom engine you implement, if you want to // store your documents in some search engine which does not have default // support. 'search.engine-selector' => 'PhabricatorDefaultSearchEngineSelector', // -- Differential ---------------------------------------------------------- // 'differential.revision-custom-detail-renderer' => null, // Array for custom remarkup rules. The array should have a list of // class names of classes that extend PhutilRemarkupRule 'differential.custom-remarkup-rules' => null, // Array for custom remarkup block rules. The array should have a list of // class names of classes that extend PhutilRemarkupEngineBlockRule 'differential.custom-remarkup-block-rules' => null, // List of file regexps where whitespace is meaningful and should not // use 'ignore-all' by default 'differential.whitespace-matters' => array( '/\.py$/', '/\.l?hs$/', ), 'differential.field-selector' => 'DifferentialDefaultFieldSelector', // Differential can show "Host" and "Path" fields on revisions, with // information about the machine and working directory where the // change came from. These fields are disabled by default because they may // occasionally have sensitive information; you can set this to true to // enable them. 'differential.show-host-field' => false, // Differential has a required "Test Plan" field by default, which requires // authors to fill out information about how they verified the correctness of // their changes when sending code for review. If you'd prefer not to use // this field, you can disable it here. You can also make it optional // (instead of required) below. 'differential.show-test-plan-field' => true, // Differential has a required "Test Plan" field by default. You can make it // optional by setting this to false. You can also completely remove it above, // if you prefer. 'differential.require-test-plan-field' => true, // If you set this to true, users can "!accept" revisions via email (normally, // they can take other actions but can not "!accept"). This action is disabled // by default because email authentication can be configured to be very weak, // and, socially, email "!accept" is kind of sketchy and implies revisions may // not actually be receiving thorough review. 'differential.enable-email-accept' => false, // If you set this to true, users won't need to login to view differential // revisions. Anonymous users will have read-only access and won't be able to // interact with the revisions. 'differential.anonymous-access' => false, // If you set this to true, revision author email address information will // be exposed in Conduit. This is useful for Arcanist. // // For example, consider the "arc patch DX" workflow which needs to ask // Differential for the revision DX. This data often should contain // the author's email address, eg "George Washington // " when DX is a git or mercurial revision. If this // option is false, Differential defaults to the best it can, something like // "George Washington" or "gwashington". 'differential.expose-emails-prudently' => false, // List of file regexps that should be treated as if they are generated by // an automatic process, and thus get hidden by default in differential. 'differential.generated-paths' => array( // '/config\.h$/', // '#/autobuilt/#', ), // If you set this to true, users can accept their own revisions. This action // is disabled by default because it's most likely not a behavior you want, // but it proves useful if you are working alone on a project and want to make // use of all of differential's features. 'differential.allow-self-accept' => false, // If you set this to true, any user can close any revision so long as it has // been accepted. This can be useful depending on your development model. For // example, github-style pull requests where the reviewer is often the // actual committer can benefit from turning this option to true. If false, // only the submitter can close a revision. 'differential.always-allow-close' => false, // If you set this to true, any user can reopen a revision so long as it has // been closed. This can be useful if a revision is accidentally closed or // if a developer changes his or her mind after closing a revision. If it is // false, reopening is not allowed. 'differential.allow-reopen' => false, // Revisions newer than this number of days are marked as fresh in Action // Required and Revisions Waiting on You views. Only work days (not weekends // and holidays) are included. Set to 0 to disable this feature. 'differential.days-fresh' => 1, // Similar to 'differential.days-fresh' but marks stale revisions. If the // revision is even older than it is marked as old. 'differential.days-stale' => 3, // -- Repositories ---------------------------------------------------------- // // The default location in which to store local copies of repositories. // Anything stored in this directory will be assumed to be under the // control of phabricator, which means that Phabricator will try to do some // maintenance on working copies if there are problems (such as a change // to the remote origin url). This maintenance may include completely // removing (and recloning) anything in this directory. // // When set to null, this option is ignored (i.e. Phabricator will not fully // control any working copies). 'repository.default-local-path' => null, // -- Maniphest ------------------------------------------------------------- // 'maniphest.enabled' => true, // Array of custom fields for Maniphest tasks. For details on adding custom // fields to Maniphest, see "Maniphest User Guide: Adding Custom Fields". 'maniphest.custom-fields' => array(), // Class which drives custom field construction. See "Maniphest User Guide: // Adding Custom Fields" in the documentation for more information. 'maniphest.custom-task-extensions-class' => 'ManiphestDefaultTaskExtensions', // What should the default task priority be in create flows? // See the constants in @{class:ManiphestTaskPriority} for valid values. // Defaults to "needs triage". 'maniphest.default-priority' => 90, // -- Phriction ------------------------------------------------------------- // 'phriction.enabled' => true, // -- Phame ----------------------------------------------------------------- // // Should Phame users have Disqus comment widget, and if so what's the // website shortname to use? For example, secure.phabricator.org uses // "phabricator", which we registered with Disqus. If you aren't familiar // with Disqus, see: // Disqus quick start guide - http://docs.disqus.com/help/4/ // Information on shortnames - http://docs.disqus.com/help/68/ 'disqus.shortname' => null, // Directories to look for Phame skins inside of. 'phame.skins' => array( 'externals/skins/', ), // -- Remarkup -------------------------------------------------------------- // // If you enable this, linked YouTube videos will be embeded inline. This has // mild security implications (you'll leak referrers to YouTube) and is pretty // silly (but sort of awesome). 'remarkup.enable-embedded-youtube' => false, // -- Cache ----------------------------------------------------------------- // // Set this to false to disable the use of gzdeflate()-based compression in // some caches. This may give you less performant (but more debuggable) // caching. 'cache.enable-deflate' => true, // -- Garbage Collection ---------------------------------------------------- // // Phabricator generates various logs and caches in the database which can // be garbage collected after a while to make the total data size more // manageable. To run garbage collection, launch a // PhabricatorGarbageCollector daemon. // These 'ttl' keys configure how much old data the GC daemon keeps around. // Objects older than the ttl will be collected. Set any value to 0 to store // data indefinitely. 'gcdaemon.ttl.herald-transcripts' => 30 * (24 * 60 * 60), 'gcdaemon.ttl.daemon-logs' => 7 * (24 * 60 * 60), 'gcdaemon.ttl.differential-parse-cache' => 14 * (24 * 60 * 60), 'gcdaemon.ttl.markup-cache' => 30 * (24 * 60 * 60), 'gcdaemon.ttl.task-archive' => 14 * (24 * 60 * 60), 'gcdaemon.ttl.general-cache' => 30 * (24 * 60 * 60), // -- Feed ------------------------------------------------------------------ // // If you set this to true, you can embed Phabricator activity feeds in other // pages using iframes. These feeds are completely public, and a login is not // required to view them! This is intended for things like open source // projects that want to expose an activity feed on the project homepage. // // NOTE: You must also set `policy.allow-public` to true for this setting // to work properly. 'feed.public' => false, // If you set this to a list of http URIs, when a feed story is published a // task will be created for each uri that posts the story data to the uri. // Daemons automagically retry failures 100 times, waiting $fail_count * 60s // between each subsequent failure. Be sure to keep the daemon console // (/daemon/) open while developing and testing your end points. // // NOTE: URIs are not validated, the URI must return http status 200 within // 30 seconds, and no permission checks are performed. 'feed.http-hooks' => array(), // -- Drydock --------------------------------------------------------------- // // If you want to use Drydock's builtin EC2 Blueprints, configure your AWS // EC2 credentials here. 'amazon-ec2.access-key' => null, 'amazon-ec2.secret-key' => null, // -- Customization --------------------------------------------------------- // // Paths to additional phutil libraries to load. 'load-libraries' => array(), 'aphront.default-application-configuration-class' => 'AphrontDefaultApplicationConfiguration', 'controller.oauth-registration' => 'PhabricatorOAuthDefaultRegistrationController', // Directory that phd (the Phabricator daemon control script) should use to // track running daemons. 'phd.pid-directory' => '/var/tmp/phd/pid', // Directory that the Phabricator daemons should use to store the log file 'phd.log-directory' => '/var/tmp/phd/log', // Number of "TaskMaster" daemons that "phd start" should start. You can // raise this if you have a task backlog, or explicitly launch more with // "phd launch taskmaster". 'phd.start-taskmasters' => 4, // Launch daemons in "verbose" mode by default. This creates a lot of output, // but can help debug issues. Daemons launched in debug mode with "phd debug" // are always launched in verbose mode. See also 'phd.trace'. 'phd.verbose' => false, // Launch daemons in "trace" mode by default. This creates an ENORMOUS amount // of output, but can help debug issues. Daemons launched in debug mode with // "phd debug" are always launched in trace mdoe. See also 'phd.verbose'. 'phd.trace' => false, // Path to custom celerity resource map relative to 'phabricator/src'. // See also `scripts/celerity_mapper.php`. 'celerity.resource-path' => '__celerity_resource_map__.php', // This value is an input to the hash function when building resource hashes. // It has no security value, but if you accidentally poison user caches (by // pushing a bad patch or having something go wrong with a CDN, e.g.) you can // change this to something else and rebuild the Celerity map to break user // caches. Unless you are doing Celerity development, it is exceptionally // unlikely that you need to modify this. 'celerity.resource-hash' => 'd9455ea150622ee044f7931dabfa52aa', - // In a development environment, it is desirable to force static resources - // (CSS and JS) to be read from disk on every request, so that edits to them - // appear when you reload the page even if you haven't updated the resource - // maps. This setting ensures requests will be verified against the state on - // disk. Generally, you should leave this off in production (caching behavior - // and performance improve with it off) but turn it on in development. (These - // settings are the defaults.) - 'celerity.force-disk-reads' => false, - // Minify static resources by removing whitespace and comments. You should // enable this in production, but disable it in development. 'celerity.minify' => false, // You can respond to various application events by installing listeners, // which will receive callbacks when interesting things occur. Specify a list // of classes which extend PhabricatorEventListener here. 'events.listeners' => array(), // -- Syntax Highlighting --------------------------------------------------- // // Phabricator can highlight PHP by default and use Pygments for other // languages if enabled. You can provide a custom highlighter engine by // extending class PhutilSyntaxHighlighterEngine. 'syntax-highlighter.engine' => 'PhutilDefaultSyntaxHighlighterEngine', // If you want syntax highlighting for other languages than PHP then you can // install the python package 'Pygments', make sure the 'pygmentize' script is // available in the $PATH of the webserver, and then enable this. 'pygments.enabled' => false, // In places that we display a dropdown to syntax-highlight code, // this is where that list is defined. // Syntax is 'lexer-name' => 'Display Name', 'pygments.dropdown-choices' => array( 'apacheconf' => 'Apache Configuration', 'bash' => 'Bash Scripting', 'brainfuck' => 'Brainf*ck', 'c' => 'C', 'cpp' => 'C++', 'css' => 'CSS', 'd' => 'D', 'diff' => 'Diff', 'django' => 'Django Templating', 'erb' => 'Embedded Ruby/ERB', 'erlang' => 'Erlang', 'haskell' => 'Haskell', 'html' => 'HTML', 'java' => 'Java', 'js' => 'Javascript', 'mysql' => 'MySQL', 'objc' => 'Objective-C', 'perl' => 'Perl', 'php' => 'PHP', 'rest' => 'reStructuredText', 'text' => 'Plain Text', 'python' => 'Python', 'rainbow' => 'Rainbow', 'remarkup' => 'Remarkup', 'ruby' => 'Ruby', 'xml' => 'XML', ), // This is an override list of regular expressions which allows you to choose // what language files are highlighted as. If your projects have certain rules // about filenames or use unusual or ambiguous language extensions, you can // create a mapping here. This is an ordered dictionary of regular expressions // which will be tested against the filename. They should map to either an // explicit language as a string value, or a numeric index into the captured // groups as an integer. 'syntax.filemap' => array( // Example: Treat all '*.xyz' files as PHP. // '@\\.xyz$@' => 'php', // Example: Treat 'httpd.conf' as 'apacheconf'. // '@/httpd\\.conf$@' => 'apacheconf', // Example: Treat all '*.x.bak' file as '.x'. NOTE: we map to capturing // group 1 by specifying the mapping as "1". // '@\\.([^.]+)\\.bak$@' => 1, '@\.arcconfig$@' => 'js', '@\.divinerconfig$@' => 'js', ), // Set the default monospaced font style for users who haven't set a custom // style. 'style.monospace' => '10px "Menlo", "Consolas", "Monaco", monospace', // -- Debugging ------------------------------------------------------------- // // Enable this to change HTTP redirects into normal pages with a link to the // redirection target. For example, after you submit a form you'll get a page // saying "normally, you'd be redirected...". This is useful to examine // service or profiler information on write pathways, or debug redirects. It // also makes the UX horrible for normal use, so you should enable it only // when debugging. // // NOTE: This does not currently work for forms with Javascript "workflow", // since the redirect happens in Javascript. 'debug.stop-on-redirect' => false, // Set the rate for how often to do sampled profiling. On average, one // request for every number of requests specified here will be sampled. // Set this value to 0 to completely disable profiling. In a production // environment, this value should either be set to 0 (to disable) or to // a large number (to sample only a few requests). 'debug.profile-rate' => 0, // -- Environment ---------------------------------------------------------- // // Phabricator occasionally shells out to other binaries on the server. // An example of this is the "pygmentize" command, used to syntax-highlight // code written in languages other than PHP. By default, it is assumed that // these binaries are in the $PATH of the user running Phabricator (normally // 'apache', 'httpd', or 'nobody'). Here you can add extra directories to // the $PATH environment variable, for when these binaries are in non-standard // locations. 'environment.append-paths' => array(), // -- Audit ---------------------------------------------------------- // // Controls whether or not task creator can Close Audits 'audit.can-author-close-audit' => false, ); diff --git a/conf/development.conf.php b/conf/development.conf.php index c18382bcf..704011402 100644 --- a/conf/development.conf.php +++ b/conf/development.conf.php @@ -1,11 +1,8 @@ true, 'darkconsole.enabled' => true, - 'celerity.force-disk-reads' => true, - 'phabricator.show-stack-traces' => true, - 'phabricator.show-error-callout' => true, - 'celerity.minify' => false, ) + phabricator_read_config_file('default'); diff --git a/externals/javelinjs/src/core/Event.js b/externals/javelinjs/src/core/Event.js index 912ee14e0..32f8cf07a 100644 --- a/externals/javelinjs/src/core/Event.js +++ b/externals/javelinjs/src/core/Event.js @@ -1,321 +1,338 @@ /** * @requires javelin-install * @provides javelin-event * @javelin */ /** * A generic event, routed by @{class:JX.Stratcom}. All events within Javelin * are represented by a {@class:JX.Event}, regardless of whether they originate * from a native DOM event (like a mouse click) or are custom application * events. * * See @{article:Concepts: Event Delegation} for an introduction to Javelin's * event delegation model. * * Events have a propagation model similar to native Javascript events, in that * they can be stopped with stop() (which stops them from continuing to * propagate to other handlers) or prevented with prevent() (which prevents them * from taking their default action, like following a link). You can do both at * once with kill(). * * @task stop Stopping Event Behaviors * @task info Getting Event Information * @group event */ JX.install('Event', { members : { /** * Stop an event from continuing to propagate. No other handler will * receive this event, but its default behavior will still occur. See * ""Using Events"" for more information on the distinction between * 'stopping' and 'preventing' an event. See also prevent() (which prevents * an event but does not stop it) and kill() (which stops and prevents an * event). * * @return this * @task stop */ stop : function() { var r = this.getRawEvent(); if (r) { r.cancelBubble = true; r.stopPropagation && r.stopPropagation(); } this.setStopped(true); return this; }, /** * Prevent an event's default action. This depends on the event type, but * the common default actions are following links, submitting forms, * and typing text. Event prevention is generally used when you have a link * or form which work properly without Javascript but have a specialized * Javascript behavior. When you intercept the event and make the behavior * occur, you prevent it to keep the browser from following the link. * * Preventing an event does not stop it from propagating, so other handlers * will still receive it. See ""Using Events"" for more information on the * distinction between 'stopping' and 'preventing' an event. See also * stop() (which stops an event but does not prevent it) and kill() * (which stops and prevents an event). * * @return this * @task stop */ prevent : function() { var r = this.getRawEvent(); if (r) { r.returnValue = false; r.preventDefault && r.preventDefault(); } this.setPrevented(true); return this; }, /** * Stop and prevent an event, which stops it from propagating and prevents * its defualt behavior. This is a convenience function, see stop() and * prevent() for information on what it means to stop or prevent an event. * * @return this * @task stop */ kill : function() { this.prevent(); this.stop(); return this; }, /** * Get the special key (like tab or return), if any, associated with this * event. Browsers report special keys differently; this method allows you * to identify a keypress in a browser-agnostic way. Note that this detects * only some special keys: delete, tab, return escape, left, up, right, * down. * * For example, if you want to react to the escape key being pressed, you * could install a listener like this: * * JX.Stratcom.listen('keydown', 'example', function(e) { * if (e.getSpecialKey() == 'esc') { * JX.log("You pressed 'Escape'! Well done! Bravo!"); * } * }); * * @return string|null ##null## if there is no associated special key, * or one of the strings 'delete', 'tab', 'return', * 'esc', 'left', 'up', 'right', or 'down'. * @task info */ getSpecialKey : function() { var r = this.getRawEvent(); if (!r || r.shiftKey) { return null; } return JX.Event._keymap[r.keyCode] || null; }, /** * Get whether the mouse button associated with the mouse event is the * right-side button in a browser-agnostic way. * * @return bool * @task info */ isRightButton : function() { var r = this.getRawEvent(); return r.which == 3 || r.button == 2; }, - - + /** - * Determine if a click event is a normal click (left mouse button, no + * Determine if a mouse event is a normal event (left mouse button, no * modifier keys). * * @return bool * @task info */ - isNormalClick : function() { - if (this.getType() != 'click') { + isNormalMouseEvent : function() { + var supportedEvents = ['click','mouseup','mousedown']; + + if (supportedEvents.indexOf(this.getType()) == -1) { return false; } var r = this.getRawEvent(); if (r.metaKey || r.altKey || r.ctrlkey || r.shiftKey) { return false; } if (('which' in r) && (r.which != 1)) { return false; } if (('button' in r) && r.button) { return false; } return true; }, + /** + * Determine if a click event is a normal click (left mouse button, no + * modifier keys). + * + * @return bool + * @task info + */ + isNormalClick : function() { + if (this.getType() != 'click') { + return false; + } + + return this.isNormalMouseEvent(); + }, + + /** * Get the node corresponding to the specified key in this event's node map. * This is a simple helper method that makes the API for accessing nodes * less ugly. * * JX.Stratcom.listen('click', 'tag:a', function(e) { * var a = e.getNode('tag:a'); * // do something with the link that was clicked * }); * * @param string sigil or stratcom node key * @return node|null Node mapped to the specified key, or null if it the * key does not exist. The available keys include: * - 'tag:'+tag - first node of each type * - 'id:'+id - all nodes with an id * - sigil - first node of each sigil * @task info */ getNode : function(key) { return this.getNodes()[key] || null; }, /** * Get the metadata associated with the node that corresponds to the key * in this event's node map. This is a simple helper method that makes * the API for accessing metadata associated with specific nodes less ugly. * * JX.Stratcom.listen('click', 'tag:a', function(event) { * var anchorData = event.getNodeData('tag:a'); * // do something with the metadata of the link that was clicked * }); * * @param string sigil or stratcom node key * @return dict dictionary of the node's metadata * @task info */ getNodeData : function(key) { // Evade static analysis - JX.Stratcom return JX['Stratcom'].getData(this.getNode(key)); } }, statics : { _keymap : { 8 : 'delete', 9 : 'tab', 13 : 'return', 27 : 'esc', 37 : 'left', 38 : 'up', 39 : 'right', 40 : 'down', 63232 : 'up', 63233 : 'down', 62234 : 'left', 62235 : 'right' } }, properties : { /** * Native Javascript event which generated this @{class:JX.Event}. Not every * event is generated by a native event, so there may be ##null## in * this field. * * @type Event|null * @task info */ rawEvent : null, /** * String describing the event type, like 'click' or 'mousedown'. This * may also be an application or object event. * * @type string * @task info */ type : null, /** * If available, the DOM node where this event occurred. For example, if * this event is a click on a button, the target will be the button which * was clicked. Application events will not have a target, so this property * will return the value ##null##. * * @type DOMNode|null * @task info */ target : null, /** * Metadata attached to nodes associated with this event. * * For native events, the DOM is walked from the event target to the root * element. Each sigil which is encountered while walking up the tree is * added to the map as a key. If the node has associated metainformation, * it is set as the value; otherwise, the value is null. * * @type dict * @task info */ data : null, /** * Sigil path this event was activated from. TODO: explain this * * @type list * @task info */ path : [], /** * True if propagation of the event has been stopped. See stop(). * * @type bool * @task stop */ stopped : false, /** * True if default behavior of the event has been prevented. See prevent(). * * @type bool * @task stop */ prevented : false, /** * @task info */ nodes : {}, /** * @task info */ nodeDistances : {} }, /** * @{class:JX.Event} installs a toString() method in ##__DEV__## which allows * you to log or print events and get a reasonable representation of them: * * Event<'click', ['path', 'stuff'], [object HTMLDivElement]> */ initialize : function() { if (__DEV__) { JX.Event.prototype.toString = function() { var path = '['+this.getPath().join(', ')+']'; return 'Event<'+this.getType()+', '+path+', '+this.getTarget()+'>'; } } } }); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 70424e5d7..f587f31e1 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1,2900 +1,2902 @@ 2, 'class' => array( 'Aphront304Response' => 'aphront/response/Aphront304Response.php', 'Aphront400Response' => 'aphront/response/Aphront400Response.php', 'Aphront403Response' => 'aphront/response/Aphront403Response.php', 'Aphront404Response' => 'aphront/response/Aphront404Response.php', 'AphrontAjaxResponse' => 'aphront/response/AphrontAjaxResponse.php', 'AphrontApplicationConfiguration' => 'aphront/configuration/AphrontApplicationConfiguration.php', 'AphrontAttachedFileView' => 'view/control/AphrontAttachedFileView.php', 'AphrontCSRFException' => 'aphront/exception/AphrontCSRFException.php', 'AphrontCalendarEventView' => 'applications/calendar/view/AphrontCalendarEventView.php', 'AphrontCalendarMonthView' => 'applications/calendar/view/AphrontCalendarMonthView.php', 'AphrontContextBarView' => 'view/layout/AphrontContextBarView.php', 'AphrontController' => 'aphront/AphrontController.php', 'AphrontCrumbsView' => 'view/layout/AphrontCrumbsView.php', 'AphrontCursorPagerView' => 'view/control/AphrontCursorPagerView.php', 'AphrontDefaultApplicationConfiguration' => 'aphront/configuration/AphrontDefaultApplicationConfiguration.php', 'AphrontDialogResponse' => 'aphront/response/AphrontDialogResponse.php', 'AphrontDialogView' => 'view/AphrontDialogView.php', 'AphrontErrorView' => 'view/form/AphrontErrorView.php', 'AphrontException' => 'aphront/exception/AphrontException.php', 'AphrontFileResponse' => 'aphront/response/AphrontFileResponse.php', 'AphrontFormCheckboxControl' => 'view/form/control/AphrontFormCheckboxControl.php', 'AphrontFormControl' => 'view/form/control/AphrontFormControl.php', 'AphrontFormDateControl' => 'view/form/control/AphrontFormDateControl.php', 'AphrontFormDividerControl' => 'view/form/control/AphrontFormDividerControl.php', 'AphrontFormDragAndDropUploadControl' => 'view/form/control/AphrontFormDragAndDropUploadControl.php', 'AphrontFormFileControl' => 'view/form/control/AphrontFormFileControl.php', 'AphrontFormImageControl' => 'view/form/control/AphrontFormImageControl.php', 'AphrontFormInsetView' => 'view/form/AphrontFormInsetView.php', 'AphrontFormLayoutView' => 'view/form/AphrontFormLayoutView.php', 'AphrontFormMarkupControl' => 'view/form/control/AphrontFormMarkupControl.php', 'AphrontFormPasswordControl' => 'view/form/control/AphrontFormPasswordControl.php', 'AphrontFormPolicyControl' => 'view/form/control/AphrontFormPolicyControl.php', 'AphrontFormRadioButtonControl' => 'view/form/control/AphrontFormRadioButtonControl.php', 'AphrontFormRecaptchaControl' => 'view/form/control/AphrontFormRecaptchaControl.php', 'AphrontFormSelectControl' => 'view/form/control/AphrontFormSelectControl.php', 'AphrontFormStaticControl' => 'view/form/control/AphrontFormStaticControl.php', 'AphrontFormSubmitControl' => 'view/form/control/AphrontFormSubmitControl.php', 'AphrontFormTextAreaControl' => 'view/form/control/AphrontFormTextAreaControl.php', 'AphrontFormTextControl' => 'view/form/control/AphrontFormTextControl.php', 'AphrontFormToggleButtonsControl' => 'view/form/control/AphrontFormToggleButtonsControl.php', 'AphrontFormTokenizerControl' => 'view/form/control/AphrontFormTokenizerControl.php', 'AphrontFormView' => 'view/form/AphrontFormView.php', 'AphrontHTMLResponse' => 'aphront/response/AphrontHTMLResponse.php', 'AphrontHTTPSink' => 'aphront/sink/AphrontHTTPSink.php', 'AphrontHTTPSinkTestCase' => 'aphront/sink/__tests__/AphrontHTTPSinkTestCase.php', 'AphrontIsolatedDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontIsolatedDatabaseConnectionTestCase.php', 'AphrontIsolatedHTTPSink' => 'aphront/sink/AphrontIsolatedHTTPSink.php', 'AphrontJSONResponse' => 'aphront/response/AphrontJSONResponse.php', 'AphrontJavelinView' => 'view/AphrontJavelinView.php', 'AphrontKeyboardShortcutsAvailableView' => 'view/widget/AphrontKeyboardShortcutsAvailableView.php', 'AphrontListFilterView' => 'view/layout/AphrontListFilterView.php', 'AphrontMiniPanelView' => 'view/layout/AphrontMiniPanelView.php', 'AphrontMoreView' => 'view/layout/AphrontMoreView.php', 'AphrontMySQLDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontMySQLDatabaseConnectionTestCase.php', 'AphrontNullView' => 'view/AphrontNullView.php', 'AphrontPHPHTTPSink' => 'aphront/sink/AphrontPHPHTTPSink.php', 'AphrontPageView' => 'view/page/AphrontPageView.php', 'AphrontPagerView' => 'view/control/AphrontPagerView.php', 'AphrontPanelView' => 'view/layout/AphrontPanelView.php', 'AphrontPlainTextResponse' => 'aphront/response/AphrontPlainTextResponse.php', 'AphrontProxyResponse' => 'aphront/response/AphrontProxyResponse.php', 'AphrontRedirectException' => 'aphront/exception/AphrontRedirectException.php', 'AphrontRedirectResponse' => 'aphront/response/AphrontRedirectResponse.php', 'AphrontReloadResponse' => 'aphront/response/AphrontReloadResponse.php', 'AphrontRequest' => 'aphront/AphrontRequest.php', 'AphrontRequestFailureView' => 'view/page/AphrontRequestFailureView.php', 'AphrontRequestTestCase' => 'aphront/__tests__/AphrontRequestTestCase.php', 'AphrontResponse' => 'aphront/response/AphrontResponse.php', 'AphrontSideNavFilterView' => 'view/layout/AphrontSideNavFilterView.php', 'AphrontTableView' => 'view/control/AphrontTableView.php', 'AphrontTagView' => 'view/AphrontTagView.php', 'AphrontTokenizerTemplateView' => 'view/control/AphrontTokenizerTemplateView.php', 'AphrontTypeaheadTemplateView' => 'view/control/AphrontTypeaheadTemplateView.php', 'AphrontURIMapper' => 'aphront/AphrontURIMapper.php', 'AphrontUsageException' => 'aphront/exception/AphrontUsageException.php', 'AphrontView' => 'view/AphrontView.php', 'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php', 'CelerityAPI' => 'infrastructure/celerity/CelerityAPI.php', 'CelerityPhabricatorResourceController' => 'infrastructure/celerity/CelerityPhabricatorResourceController.php', 'CelerityResourceController' => 'infrastructure/celerity/CelerityResourceController.php', 'CelerityResourceGraph' => 'infrastructure/celerity/CelerityResourceGraph.php', 'CelerityResourceMap' => 'infrastructure/celerity/CelerityResourceMap.php', 'CelerityResourceTransformer' => 'infrastructure/celerity/CelerityResourceTransformer.php', 'CelerityResourceTransformerTestCase' => 'infrastructure/celerity/__tests__/CelerityResourceTransformerTestCase.php', 'CeleritySpriteGenerator' => 'infrastructure/celerity/CeleritySpriteGenerator.php', 'CelerityStaticResourceResponse' => 'infrastructure/celerity/CelerityStaticResourceResponse.php', 'ConduitAPIMethod' => 'applications/conduit/method/ConduitAPIMethod.php', 'ConduitAPIRequest' => 'applications/conduit/protocol/ConduitAPIRequest.php', 'ConduitAPIResponse' => 'applications/conduit/protocol/ConduitAPIResponse.php', 'ConduitAPI_arcanist_Method' => 'applications/arcanist/conduit/ConduitAPI_arcanist_Method.php', 'ConduitAPI_arcanist_projectinfo_Method' => 'applications/arcanist/conduit/ConduitAPI_arcanist_projectinfo_Method.php', 'ConduitAPI_audit_Method' => 'applications/audit/conduit/ConduitAPI_audit_Method.php', 'ConduitAPI_audit_query_Method' => 'applications/audit/conduit/ConduitAPI_audit_query_Method.php', 'ConduitAPI_chatlog_Method' => 'applications/chatlog/conduit/ConduitAPI_chatlog_Method.php', 'ConduitAPI_chatlog_query_Method' => 'applications/chatlog/conduit/ConduitAPI_chatlog_query_Method.php', 'ConduitAPI_chatlog_record_Method' => 'applications/chatlog/conduit/ConduitAPI_chatlog_record_Method.php', 'ConduitAPI_conduit_connect_Method' => 'applications/conduit/method/ConduitAPI_conduit_connect_Method.php', 'ConduitAPI_conduit_getcertificate_Method' => 'applications/conduit/method/ConduitAPI_conduit_getcertificate_Method.php', 'ConduitAPI_conduit_ping_Method' => 'applications/conduit/method/ConduitAPI_conduit_ping_Method.php', 'ConduitAPI_conduit_query_Method' => 'applications/conduit/method/ConduitAPI_conduit_query_Method.php', 'ConduitAPI_daemon_launched_Method' => 'applications/daemon/conduit/ConduitAPI_daemon_launched_Method.php', 'ConduitAPI_daemon_log_Method' => 'applications/daemon/conduit/ConduitAPI_daemon_log_Method.php', 'ConduitAPI_daemon_setstatus_Method' => 'applications/daemon/conduit/ConduitAPI_daemon_setstatus_Method.php', 'ConduitAPI_differential_Method' => 'applications/differential/conduit/ConduitAPI_differential_Method.php', 'ConduitAPI_differential_close_Method' => 'applications/differential/conduit/ConduitAPI_differential_close_Method.php', 'ConduitAPI_differential_createcomment_Method' => 'applications/differential/conduit/ConduitAPI_differential_createcomment_Method.php', 'ConduitAPI_differential_creatediff_Method' => 'applications/differential/conduit/ConduitAPI_differential_creatediff_Method.php', 'ConduitAPI_differential_createinline_Method' => 'applications/differential/conduit/ConduitAPI_differential_createinline_Method.php', 'ConduitAPI_differential_createrawdiff_Method' => 'applications/differential/conduit/ConduitAPI_differential_createrawdiff_Method.php', 'ConduitAPI_differential_createrevision_Method' => 'applications/differential/conduit/ConduitAPI_differential_createrevision_Method.php', 'ConduitAPI_differential_find_Method' => 'applications/differential/conduit/ConduitAPI_differential_find_Method.php', 'ConduitAPI_differential_finishpostponedlinters_Method' => 'applications/differential/conduit/ConduitAPI_differential_finishpostponedlinters_Method.php', 'ConduitAPI_differential_getalldiffs_Method' => 'applications/differential/conduit/ConduitAPI_differential_getalldiffs_Method.php', 'ConduitAPI_differential_getcommitmessage_Method' => 'applications/differential/conduit/ConduitAPI_differential_getcommitmessage_Method.php', 'ConduitAPI_differential_getcommitpaths_Method' => 'applications/differential/conduit/ConduitAPI_differential_getcommitpaths_Method.php', 'ConduitAPI_differential_getdiff_Method' => 'applications/differential/conduit/ConduitAPI_differential_getdiff_Method.php', 'ConduitAPI_differential_getrevision_Method' => 'applications/differential/conduit/ConduitAPI_differential_getrevision_Method.php', 'ConduitAPI_differential_getrevisioncomments_Method' => 'applications/differential/conduit/ConduitAPI_differential_getrevisioncomments_Method.php', 'ConduitAPI_differential_getrevisionfeedback_Method' => 'applications/differential/conduit/ConduitAPI_differential_getrevisionfeedback_Method.php', 'ConduitAPI_differential_markcommitted_Method' => 'applications/differential/conduit/ConduitAPI_differential_markcommitted_Method.php', 'ConduitAPI_differential_parsecommitmessage_Method' => 'applications/differential/conduit/ConduitAPI_differential_parsecommitmessage_Method.php', 'ConduitAPI_differential_query_Method' => 'applications/differential/conduit/ConduitAPI_differential_query_Method.php', 'ConduitAPI_differential_setdiffproperty_Method' => 'applications/differential/conduit/ConduitAPI_differential_setdiffproperty_Method.php', 'ConduitAPI_differential_updaterevision_Method' => 'applications/differential/conduit/ConduitAPI_differential_updaterevision_Method.php', 'ConduitAPI_differential_updateunitresults_Method' => 'applications/differential/conduit/ConduitAPI_differential_updateunitresults_Method.php', 'ConduitAPI_diffusion_findsymbols_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_findsymbols_Method.php', 'ConduitAPI_diffusion_getcommits_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_getcommits_Method.php', 'ConduitAPI_diffusion_getlintmessages_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_getlintmessages_Method.php', 'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'applications/diffusion/conduit/ConduitAPI_diffusion_getrecentcommitsbypath_Method.php', 'ConduitAPI_feed_publish_Method' => 'applications/feed/conduit/ConduitAPI_feed_publish_Method.php', 'ConduitAPI_feed_query_Method' => 'applications/feed/conduit/ConduitAPI_feed_query_Method.php', 'ConduitAPI_file_download_Method' => 'applications/files/conduit/ConduitAPI_file_download_Method.php', 'ConduitAPI_file_info_Method' => 'applications/files/conduit/ConduitAPI_file_info_Method.php', 'ConduitAPI_file_upload_Method' => 'applications/files/conduit/ConduitAPI_file_upload_Method.php', 'ConduitAPI_flag_Method' => 'applications/flag/conduit/ConduitAPI_flag_Method.php', 'ConduitAPI_flag_delete_Method' => 'applications/flag/conduit/ConduitAPI_flag_delete_Method.php', 'ConduitAPI_flag_edit_Method' => 'applications/flag/conduit/ConduitAPI_flag_edit_Method.php', 'ConduitAPI_flag_query_Method' => 'applications/flag/conduit/ConduitAPI_flag_query_Method.php', 'ConduitAPI_macro_Method' => 'applications/macro/conduit/ConduitAPI_macro_Method.php', 'ConduitAPI_macro_query_Method' => 'applications/macro/conduit/ConduitAPI_macro_query_Method.php', 'ConduitAPI_maniphest_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_Method.php', 'ConduitAPI_maniphest_createtask_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_createtask_Method.php', 'ConduitAPI_maniphest_find_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_find_Method.php', 'ConduitAPI_maniphest_gettasktransactions_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_gettasktransactions_Method.php', 'ConduitAPI_maniphest_info_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_info_Method.php', 'ConduitAPI_maniphest_query_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_query_Method.php', 'ConduitAPI_maniphest_update_Method' => 'applications/maniphest/conduit/ConduitAPI_maniphest_update_Method.php', 'ConduitAPI_owners_query_Method' => 'applications/owners/conduit/ConduitAPI_owners_query_Method.php', 'ConduitAPI_paste_Method' => 'applications/paste/conduit/ConduitAPI_paste_Method.php', 'ConduitAPI_paste_create_Method' => 'applications/paste/conduit/ConduitAPI_paste_create_Method.php', 'ConduitAPI_paste_info_Method' => 'applications/paste/conduit/ConduitAPI_paste_info_Method.php', 'ConduitAPI_paste_query_Method' => 'applications/paste/conduit/ConduitAPI_paste_query_Method.php', 'ConduitAPI_phid_Method' => 'applications/phid/conduit/ConduitAPI_phid_Method.php', 'ConduitAPI_phid_info_Method' => 'applications/phid/conduit/ConduitAPI_phid_info_Method.php', 'ConduitAPI_phid_lookup_Method' => 'applications/phid/conduit/ConduitAPI_phid_lookup_Method.php', 'ConduitAPI_phid_query_Method' => 'applications/phid/conduit/ConduitAPI_phid_query_Method.php', 'ConduitAPI_phpast_getast_Method' => 'applications/phpast/conduit/ConduitAPI_phpast_getast_Method.php', 'ConduitAPI_phpast_version_Method' => 'applications/phpast/conduit/ConduitAPI_phpast_version_Method.php', 'ConduitAPI_phriction_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_Method.php', 'ConduitAPI_phriction_edit_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_edit_Method.php', 'ConduitAPI_phriction_history_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_history_Method.php', 'ConduitAPI_phriction_info_Method' => 'applications/phriction/conduit/ConduitAPI_phriction_info_Method.php', 'ConduitAPI_project_Method' => 'applications/project/conduit/ConduitAPI_project_Method.php', 'ConduitAPI_project_query_Method' => 'applications/project/conduit/ConduitAPI_project_query_Method.php', 'ConduitAPI_remarkup_process_Method' => 'applications/remarkup/conduit/ConduitAPI_remarkup_process_Method.php', 'ConduitAPI_repository_Method' => 'applications/repository/conduit/ConduitAPI_repository_Method.php', 'ConduitAPI_repository_create_Method' => 'applications/repository/conduit/ConduitAPI_repository_create_Method.php', 'ConduitAPI_repository_query_Method' => 'applications/repository/conduit/ConduitAPI_repository_query_Method.php', 'ConduitAPI_slowvote_info_Method' => 'applications/slowvote/conduit/ConduitAPI_slowvote_info_Method.php', 'ConduitAPI_user_Method' => 'applications/people/conduit/ConduitAPI_user_Method.php', 'ConduitAPI_user_addstatus_Method' => 'applications/people/conduit/ConduitAPI_user_addstatus_Method.php', 'ConduitAPI_user_disable_Method' => 'applications/people/conduit/ConduitAPI_user_disable_Method.php', 'ConduitAPI_user_enable_Method' => 'applications/people/conduit/ConduitAPI_user_enable_Method.php', 'ConduitAPI_user_find_Method' => 'applications/people/conduit/ConduitAPI_user_find_Method.php', 'ConduitAPI_user_info_Method' => 'applications/people/conduit/ConduitAPI_user_info_Method.php', 'ConduitAPI_user_query_Method' => 'applications/people/conduit/ConduitAPI_user_query_Method.php', 'ConduitAPI_user_removestatus_Method' => 'applications/people/conduit/ConduitAPI_user_removestatus_Method.php', 'ConduitAPI_user_whoami_Method' => 'applications/people/conduit/ConduitAPI_user_whoami_Method.php', 'ConduitCall' => 'applications/conduit/call/ConduitCall.php', 'ConduitCallTestCase' => 'applications/conduit/call/__tests__/ConduitCallTestCase.php', 'ConduitException' => 'applications/conduit/protocol/ConduitException.php', 'ConduitSSHWorkflow' => 'applications/conduit/ssh/ConduitSSHWorkflow.php', 'ConpherenceConfigOptions' => 'applications/conpherence/config/ConpherenceConfigOptions.php', 'ConpherenceConstants' => 'applications/conpherence/constants/ConpherenceConstants.php', 'ConpherenceController' => 'applications/conpherence/controller/ConpherenceController.php', 'ConpherenceDAO' => 'applications/conpherence/storage/ConpherenceDAO.php', 'ConpherenceEditor' => 'applications/conpherence/editor/ConpherenceEditor.php', 'ConpherenceListController' => 'applications/conpherence/controller/ConpherenceListController.php', 'ConpherenceMenuItemView' => 'applications/conpherence/view/ConpherenceMenuItemView.php', 'ConpherenceNewController' => 'applications/conpherence/controller/ConpherenceNewController.php', 'ConpherenceParticipant' => 'applications/conpherence/storage/ConpherenceParticipant.php', 'ConpherenceParticipantQuery' => 'applications/conpherence/query/ConpherenceParticipantQuery.php', 'ConpherenceParticipationStatus' => 'applications/conpherence/constants/ConpherenceParticipationStatus.php', 'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php', 'ConpherenceThread' => 'applications/conpherence/storage/ConpherenceThread.php', 'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php', 'ConpherenceTransaction' => 'applications/conpherence/storage/ConpherenceTransaction.php', 'ConpherenceTransactionComment' => 'applications/conpherence/storage/ConpherenceTransactionComment.php', 'ConpherenceTransactionQuery' => 'applications/conpherence/query/ConpherenceTransactionQuery.php', 'ConpherenceTransactionType' => 'applications/conpherence/constants/ConpherenceTransactionType.php', 'ConpherenceTransactionView' => 'applications/conpherence/view/ConpherenceTransactionView.php', 'ConpherenceUpdateController' => 'applications/conpherence/controller/ConpherenceUpdateController.php', 'ConpherenceViewController' => 'applications/conpherence/controller/ConpherenceViewController.php', 'DarkConsoleController' => 'aphront/console/DarkConsoleController.php', 'DarkConsoleCore' => 'aphront/console/DarkConsoleCore.php', 'DarkConsoleDataController' => 'aphront/console/DarkConsoleDataController.php', 'DarkConsoleErrorLogPlugin' => 'aphront/console/plugin/DarkConsoleErrorLogPlugin.php', 'DarkConsoleErrorLogPluginAPI' => 'aphront/console/plugin/errorlog/DarkConsoleErrorLogPluginAPI.php', 'DarkConsoleEventPlugin' => 'aphront/console/plugin/DarkConsoleEventPlugin.php', 'DarkConsoleEventPluginAPI' => 'aphront/console/plugin/event/DarkConsoleEventPluginAPI.php', 'DarkConsolePlugin' => 'aphront/console/plugin/DarkConsolePlugin.php', 'DarkConsoleRequestPlugin' => 'aphront/console/plugin/DarkConsoleRequestPlugin.php', 'DarkConsoleServicesPlugin' => 'aphront/console/plugin/DarkConsoleServicesPlugin.php', 'DarkConsoleXHProfPlugin' => 'aphront/console/plugin/DarkConsoleXHProfPlugin.php', 'DarkConsoleXHProfPluginAPI' => 'aphront/console/plugin/xhprof/DarkConsoleXHProfPluginAPI.php', 'DatabaseConfigurationProvider' => 'infrastructure/storage/configuration/DatabaseConfigurationProvider.php', 'DefaultDatabaseConfigurationProvider' => 'infrastructure/storage/configuration/DefaultDatabaseConfigurationProvider.php', 'DifferentialAction' => 'applications/differential/constants/DifferentialAction.php', 'DifferentialActionHasNoEffectException' => 'applications/differential/exception/DifferentialActionHasNoEffectException.php', 'DifferentialAddCommentView' => 'applications/differential/view/DifferentialAddCommentView.php', 'DifferentialAffectedPath' => 'applications/differential/storage/DifferentialAffectedPath.php', 'DifferentialApplyPatchFieldSpecification' => 'applications/differential/field/specification/DifferentialApplyPatchFieldSpecification.php', 'DifferentialArcanistProjectFieldSpecification' => 'applications/differential/field/specification/DifferentialArcanistProjectFieldSpecification.php', 'DifferentialAuditorsFieldSpecification' => 'applications/differential/field/specification/DifferentialAuditorsFieldSpecification.php', 'DifferentialAuthorFieldSpecification' => 'applications/differential/field/specification/DifferentialAuthorFieldSpecification.php', 'DifferentialAuxiliaryField' => 'applications/differential/storage/DifferentialAuxiliaryField.php', 'DifferentialBlameRevisionFieldSpecification' => 'applications/differential/field/specification/DifferentialBlameRevisionFieldSpecification.php', 'DifferentialBranchFieldSpecification' => 'applications/differential/field/specification/DifferentialBranchFieldSpecification.php', 'DifferentialCCWelcomeMail' => 'applications/differential/mail/DifferentialCCWelcomeMail.php', 'DifferentialCCsFieldSpecification' => 'applications/differential/field/specification/DifferentialCCsFieldSpecification.php', 'DifferentialChangeType' => 'applications/differential/constants/DifferentialChangeType.php', 'DifferentialChangeset' => 'applications/differential/storage/DifferentialChangeset.php', 'DifferentialChangesetDetailView' => 'applications/differential/view/DifferentialChangesetDetailView.php', 'DifferentialChangesetFileTreeSideNavBuilder' => 'applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php', 'DifferentialChangesetHTMLRenderer' => 'applications/differential/render/DifferentialChangesetHTMLRenderer.php', 'DifferentialChangesetListView' => 'applications/differential/view/DifferentialChangesetListView.php', 'DifferentialChangesetOneUpRenderer' => 'applications/differential/render/DifferentialChangesetOneUpRenderer.php', 'DifferentialChangesetOneUpTestRenderer' => 'applications/differential/render/DifferentialChangesetOneUpTestRenderer.php', 'DifferentialChangesetParser' => 'applications/differential/parser/DifferentialChangesetParser.php', 'DifferentialChangesetParserTestCase' => 'applications/differential/parser/__tests__/DifferentialChangesetParserTestCase.php', 'DifferentialChangesetRenderer' => 'applications/differential/render/DifferentialChangesetRenderer.php', 'DifferentialChangesetTestRenderer' => 'applications/differential/render/DifferentialChangesetTestRenderer.php', 'DifferentialChangesetTwoUpRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpRenderer.php', 'DifferentialChangesetTwoUpTestRenderer' => 'applications/differential/render/DifferentialChangesetTwoUpTestRenderer.php', 'DifferentialChangesetViewController' => 'applications/differential/controller/DifferentialChangesetViewController.php', 'DifferentialComment' => 'applications/differential/storage/DifferentialComment.php', 'DifferentialCommentEditor' => 'applications/differential/editor/DifferentialCommentEditor.php', 'DifferentialCommentMail' => 'applications/differential/mail/DifferentialCommentMail.php', 'DifferentialCommentPreviewController' => 'applications/differential/controller/DifferentialCommentPreviewController.php', 'DifferentialCommentSaveController' => 'applications/differential/controller/DifferentialCommentSaveController.php', 'DifferentialCommitsFieldSpecification' => 'applications/differential/field/specification/DifferentialCommitsFieldSpecification.php', 'DifferentialConflictsFieldSpecification' => 'applications/differential/field/specification/DifferentialConflictsFieldSpecification.php', 'DifferentialController' => 'applications/differential/controller/DifferentialController.php', 'DifferentialDAO' => 'applications/differential/storage/DifferentialDAO.php', 'DifferentialDateCreatedFieldSpecification' => 'applications/differential/field/specification/DifferentialDateCreatedFieldSpecification.php', 'DifferentialDateModifiedFieldSpecification' => 'applications/differential/field/specification/DifferentialDateModifiedFieldSpecification.php', 'DifferentialDefaultFieldSelector' => 'applications/differential/field/selector/DifferentialDefaultFieldSelector.php', 'DifferentialDependenciesFieldSpecification' => 'applications/differential/field/specification/DifferentialDependenciesFieldSpecification.php', 'DifferentialDependsOnFieldSpecification' => 'applications/differential/field/specification/DifferentialDependsOnFieldSpecification.php', 'DifferentialDiff' => 'applications/differential/storage/DifferentialDiff.php', 'DifferentialDiffContentMail' => 'applications/differential/mail/DifferentialDiffContentMail.php', 'DifferentialDiffCreateController' => 'applications/differential/controller/DifferentialDiffCreateController.php', 'DifferentialDiffProperty' => 'applications/differential/storage/DifferentialDiffProperty.php', 'DifferentialDiffTableOfContentsView' => 'applications/differential/view/DifferentialDiffTableOfContentsView.php', 'DifferentialDiffTestCase' => 'applications/differential/storage/__tests__/DifferentialDiffTestCase.php', 'DifferentialDiffViewController' => 'applications/differential/controller/DifferentialDiffViewController.php', 'DifferentialException' => 'applications/differential/exception/DifferentialException.php', 'DifferentialExceptionMail' => 'applications/differential/mail/DifferentialExceptionMail.php', 'DifferentialExportPatchFieldSpecification' => 'applications/differential/field/specification/DifferentialExportPatchFieldSpecification.php', 'DifferentialFieldDataNotAvailableException' => 'applications/differential/field/exception/DifferentialFieldDataNotAvailableException.php', 'DifferentialFieldParseException' => 'applications/differential/field/exception/DifferentialFieldParseException.php', 'DifferentialFieldSelector' => 'applications/differential/field/selector/DifferentialFieldSelector.php', 'DifferentialFieldSpecification' => 'applications/differential/field/specification/DifferentialFieldSpecification.php', 'DifferentialFieldSpecificationIncompleteException' => 'applications/differential/field/exception/DifferentialFieldSpecificationIncompleteException.php', 'DifferentialFieldValidationException' => 'applications/differential/field/exception/DifferentialFieldValidationException.php', 'DifferentialFreeformFieldSpecification' => 'applications/differential/field/specification/DifferentialFreeformFieldSpecification.php', 'DifferentialGitSVNIDFieldSpecification' => 'applications/differential/field/specification/DifferentialGitSVNIDFieldSpecification.php', 'DifferentialHostFieldSpecification' => 'applications/differential/field/specification/DifferentialHostFieldSpecification.php', 'DifferentialHunk' => 'applications/differential/storage/DifferentialHunk.php', 'DifferentialHunkParser' => 'applications/differential/parser/DifferentialHunkParser.php', 'DifferentialHunkParserTestCase' => 'applications/differential/parser/__tests__/DifferentialHunkParserTestCase.php', 'DifferentialHunkTestCase' => 'applications/differential/storage/__tests__/DifferentialHunkTestCase.php', 'DifferentialInlineComment' => 'applications/differential/storage/DifferentialInlineComment.php', 'DifferentialInlineCommentEditController' => 'applications/differential/controller/DifferentialInlineCommentEditController.php', 'DifferentialInlineCommentEditView' => 'applications/differential/view/DifferentialInlineCommentEditView.php', 'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/DifferentialInlineCommentPreviewController.php', 'DifferentialInlineCommentView' => 'applications/differential/view/DifferentialInlineCommentView.php', 'DifferentialLinesFieldSpecification' => 'applications/differential/field/specification/DifferentialLinesFieldSpecification.php', 'DifferentialLintFieldSpecification' => 'applications/differential/field/specification/DifferentialLintFieldSpecification.php', 'DifferentialLintStatus' => 'applications/differential/constants/DifferentialLintStatus.php', 'DifferentialLocalCommitsView' => 'applications/differential/view/DifferentialLocalCommitsView.php', 'DifferentialMail' => 'applications/differential/mail/DifferentialMail.php', 'DifferentialMailPhase' => 'applications/differential/constants/DifferentialMailPhase.php', 'DifferentialManiphestTasksFieldSpecification' => 'applications/differential/field/specification/DifferentialManiphestTasksFieldSpecification.php', 'DifferentialNewDiffMail' => 'applications/differential/mail/DifferentialNewDiffMail.php', 'DifferentialParseRenderTestCase' => 'applications/differential/__tests__/DifferentialParseRenderTestCase.php', 'DifferentialPathFieldSpecification' => 'applications/differential/field/specification/DifferentialPathFieldSpecification.php', 'DifferentialPrimaryPaneView' => 'applications/differential/view/DifferentialPrimaryPaneView.php', 'DifferentialReplyHandler' => 'applications/differential/DifferentialReplyHandler.php', 'DifferentialResultsTableView' => 'applications/differential/view/DifferentialResultsTableView.php', 'DifferentialRevertPlanFieldSpecification' => 'applications/differential/field/specification/DifferentialRevertPlanFieldSpecification.php', 'DifferentialReviewRequestMail' => 'applications/differential/mail/DifferentialReviewRequestMail.php', 'DifferentialReviewedByFieldSpecification' => 'applications/differential/field/specification/DifferentialReviewedByFieldSpecification.php', 'DifferentialReviewerStats' => 'applications/differential/stats/DifferentialReviewerStats.php', 'DifferentialReviewerStatsTestCase' => 'applications/differential/stats/__tests__/DifferentialReviewerStatsTestCase.php', 'DifferentialReviewersFieldSpecification' => 'applications/differential/field/specification/DifferentialReviewersFieldSpecification.php', 'DifferentialRevision' => 'applications/differential/storage/DifferentialRevision.php', 'DifferentialRevisionCommentListView' => 'applications/differential/view/DifferentialRevisionCommentListView.php', 'DifferentialRevisionCommentView' => 'applications/differential/view/DifferentialRevisionCommentView.php', 'DifferentialRevisionControlSystem' => 'applications/differential/constants/DifferentialRevisionControlSystem.php', 'DifferentialRevisionDetailRenderer' => 'applications/differential/controller/DifferentialRevisionDetailRenderer.php', 'DifferentialRevisionDetailView' => 'applications/differential/view/DifferentialRevisionDetailView.php', 'DifferentialRevisionEditController' => 'applications/differential/controller/DifferentialRevisionEditController.php', 'DifferentialRevisionEditor' => 'applications/differential/editor/DifferentialRevisionEditor.php', 'DifferentialRevisionIDFieldParserTestCase' => 'applications/differential/field/specification/__tests__/DifferentialRevisionIDFieldParserTestCase.php', 'DifferentialRevisionIDFieldSpecification' => 'applications/differential/field/specification/DifferentialRevisionIDFieldSpecification.php', 'DifferentialRevisionListController' => 'applications/differential/controller/DifferentialRevisionListController.php', 'DifferentialRevisionListData' => 'applications/differential/data/DifferentialRevisionListData.php', 'DifferentialRevisionListView' => 'applications/differential/view/DifferentialRevisionListView.php', 'DifferentialRevisionQuery' => 'applications/differential/query/DifferentialRevisionQuery.php', 'DifferentialRevisionStatsController' => 'applications/differential/controller/DifferentialRevisionStatsController.php', 'DifferentialRevisionStatsView' => 'applications/differential/view/DifferentialRevisionStatsView.php', 'DifferentialRevisionStatus' => 'applications/differential/constants/DifferentialRevisionStatus.php', 'DifferentialRevisionStatusFieldSpecification' => 'applications/differential/field/specification/DifferentialRevisionStatusFieldSpecification.php', 'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/DifferentialRevisionUpdateHistoryView.php', 'DifferentialRevisionViewController' => 'applications/differential/controller/DifferentialRevisionViewController.php', 'DifferentialSearchIndexer' => 'applications/differential/search/DifferentialSearchIndexer.php', 'DifferentialSubscribeController' => 'applications/differential/controller/DifferentialSubscribeController.php', 'DifferentialSummaryFieldSpecification' => 'applications/differential/field/specification/DifferentialSummaryFieldSpecification.php', 'DifferentialTasksAttacher' => 'applications/differential/DifferentialTasksAttacher.php', 'DifferentialTestPlanFieldSpecification' => 'applications/differential/field/specification/DifferentialTestPlanFieldSpecification.php', 'DifferentialTitleFieldSpecification' => 'applications/differential/field/specification/DifferentialTitleFieldSpecification.php', 'DifferentialUnitFieldSpecification' => 'applications/differential/field/specification/DifferentialUnitFieldSpecification.php', 'DifferentialUnitStatus' => 'applications/differential/constants/DifferentialUnitStatus.php', 'DifferentialUnitTestResult' => 'applications/differential/constants/DifferentialUnitTestResult.php', 'DiffusionBranchInformation' => 'applications/diffusion/data/DiffusionBranchInformation.php', 'DiffusionBranchQuery' => 'applications/diffusion/query/branch/DiffusionBranchQuery.php', 'DiffusionBranchTableController' => 'applications/diffusion/controller/DiffusionBranchTableController.php', 'DiffusionBranchTableView' => 'applications/diffusion/view/DiffusionBranchTableView.php', 'DiffusionBrowseController' => 'applications/diffusion/controller/DiffusionBrowseController.php', 'DiffusionBrowseFileController' => 'applications/diffusion/controller/DiffusionBrowseFileController.php', 'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/DiffusionBrowseQuery.php', 'DiffusionBrowseTableView' => 'applications/diffusion/view/DiffusionBrowseTableView.php', 'DiffusionChangeController' => 'applications/diffusion/controller/DiffusionChangeController.php', 'DiffusionCommentListView' => 'applications/diffusion/view/DiffusionCommentListView.php', 'DiffusionCommentView' => 'applications/diffusion/view/DiffusionCommentView.php', 'DiffusionCommitBranchesController' => 'applications/diffusion/controller/DiffusionCommitBranchesController.php', 'DiffusionCommitChangeTableView' => 'applications/diffusion/view/DiffusionCommitChangeTableView.php', 'DiffusionCommitController' => 'applications/diffusion/controller/DiffusionCommitController.php', 'DiffusionCommitEditController' => 'applications/diffusion/controller/DiffusionCommitEditController.php', 'DiffusionCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionCommitParentsQuery.php', 'DiffusionCommitTagsController' => 'applications/diffusion/controller/DiffusionCommitTagsController.php', 'DiffusionCommitTagsQuery' => 'applications/diffusion/query/committags/DiffusionCommitTagsQuery.php', 'DiffusionContainsQuery' => 'applications/diffusion/query/contains/DiffusionContainsQuery.php', 'DiffusionController' => 'applications/diffusion/controller/DiffusionController.php', 'DiffusionDiffController' => 'applications/diffusion/controller/DiffusionDiffController.php', 'DiffusionDiffQuery' => 'applications/diffusion/query/diff/DiffusionDiffQuery.php', 'DiffusionEmptyResultView' => 'applications/diffusion/view/DiffusionEmptyResultView.php', 'DiffusionExistsQuery' => 'applications/diffusion/query/exists/DiffusionExistsQuery.php', 'DiffusionExternalController' => 'applications/diffusion/controller/DiffusionExternalController.php', 'DiffusionFileContent' => 'applications/diffusion/data/DiffusionFileContent.php', 'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionFileContentQuery.php', 'DiffusionGitBranchQuery' => 'applications/diffusion/query/branch/DiffusionGitBranchQuery.php', 'DiffusionGitBranchQueryTestCase' => 'applications/diffusion/query/branch/__tests__/DiffusionGitBranchQueryTestCase.php', 'DiffusionGitBrowseQuery' => 'applications/diffusion/query/browse/DiffusionGitBrowseQuery.php', 'DiffusionGitCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionGitCommitParentsQuery.php', 'DiffusionGitCommitTagsQuery' => 'applications/diffusion/query/committags/DiffusionGitCommitTagsQuery.php', 'DiffusionGitContainsQuery' => 'applications/diffusion/query/contains/DiffusionGitContainsQuery.php', 'DiffusionGitDiffQuery' => 'applications/diffusion/query/diff/DiffusionGitDiffQuery.php', 'DiffusionGitExistsQuery' => 'applications/diffusion/query/exists/DiffusionGitExistsQuery.php', 'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionGitFileContentQuery.php', 'DiffusionGitHistoryQuery' => 'applications/diffusion/query/history/DiffusionGitHistoryQuery.php', 'DiffusionGitLastModifiedQuery' => 'applications/diffusion/query/lastmodified/DiffusionGitLastModifiedQuery.php', 'DiffusionGitMergedCommitsQuery' => 'applications/diffusion/query/mergedcommits/DiffusionGitMergedCommitsQuery.php', 'DiffusionGitRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionGitRawDiffQuery.php', 'DiffusionGitRequest' => 'applications/diffusion/request/DiffusionGitRequest.php', 'DiffusionGitTagListQuery' => 'applications/diffusion/query/taglist/DiffusionGitTagListQuery.php', 'DiffusionHistoryController' => 'applications/diffusion/controller/DiffusionHistoryController.php', 'DiffusionHistoryQuery' => 'applications/diffusion/query/history/DiffusionHistoryQuery.php', 'DiffusionHistoryTableView' => 'applications/diffusion/view/DiffusionHistoryTableView.php', 'DiffusionHomeController' => 'applications/diffusion/controller/DiffusionHomeController.php', 'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php', 'DiffusionInlineCommentPreviewController' => 'applications/diffusion/controller/DiffusionInlineCommentPreviewController.php', 'DiffusionLastModifiedController' => 'applications/diffusion/controller/DiffusionLastModifiedController.php', 'DiffusionLastModifiedQuery' => 'applications/diffusion/query/lastmodified/DiffusionLastModifiedQuery.php', 'DiffusionLintController' => 'applications/diffusion/controller/DiffusionLintController.php', 'DiffusionLintDetailsController' => 'applications/diffusion/controller/DiffusionLintDetailsController.php', 'DiffusionLintSaveRunner' => 'applications/diffusion/DiffusionLintSaveRunner.php', 'DiffusionMercurialBranchQuery' => 'applications/diffusion/query/branch/DiffusionMercurialBranchQuery.php', 'DiffusionMercurialBrowseQuery' => 'applications/diffusion/query/browse/DiffusionMercurialBrowseQuery.php', 'DiffusionMercurialCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionMercurialCommitParentsQuery.php', 'DiffusionMercurialCommitTagsQuery' => 'applications/diffusion/query/committags/DiffusionMercurialCommitTagsQuery.php', 'DiffusionMercurialContainsQuery' => 'applications/diffusion/query/contains/DiffusionMercurialContainsQuery.php', 'DiffusionMercurialDiffQuery' => 'applications/diffusion/query/diff/DiffusionMercurialDiffQuery.php', 'DiffusionMercurialExistsQuery' => 'applications/diffusion/query/exists/DiffusionMercurialExistsQuery.php', 'DiffusionMercurialFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionMercurialFileContentQuery.php', 'DiffusionMercurialHistoryQuery' => 'applications/diffusion/query/history/DiffusionMercurialHistoryQuery.php', 'DiffusionMercurialLastModifiedQuery' => 'applications/diffusion/query/lastmodified/DiffusionMercurialLastModifiedQuery.php', 'DiffusionMercurialMergedCommitsQuery' => 'applications/diffusion/query/mergedcommits/DiffusionMercurialMergedCommitsQuery.php', 'DiffusionMercurialRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionMercurialRawDiffQuery.php', 'DiffusionMercurialRequest' => 'applications/diffusion/request/DiffusionMercurialRequest.php', 'DiffusionMercurialTagListQuery' => 'applications/diffusion/query/taglist/DiffusionMercurialTagListQuery.php', 'DiffusionMergedCommitsQuery' => 'applications/diffusion/query/mergedcommits/DiffusionMergedCommitsQuery.php', 'DiffusionPathChange' => 'applications/diffusion/data/DiffusionPathChange.php', 'DiffusionPathChangeQuery' => 'applications/diffusion/query/pathchange/DiffusionPathChangeQuery.php', 'DiffusionPathCompleteController' => 'applications/diffusion/controller/DiffusionPathCompleteController.php', 'DiffusionPathIDQuery' => 'applications/diffusion/query/pathid/DiffusionPathIDQuery.php', 'DiffusionPathQuery' => 'applications/diffusion/query/DiffusionPathQuery.php', 'DiffusionPathQueryTestCase' => 'applications/diffusion/query/pathid/__tests__/DiffusionPathQueryTestCase.php', 'DiffusionPathValidateController' => 'applications/diffusion/controller/DiffusionPathValidateController.php', 'DiffusionQuery' => 'applications/diffusion/query/DiffusionQuery.php', 'DiffusionRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionRawDiffQuery.php', 'DiffusionRenameHistoryQuery' => 'applications/diffusion/query/DiffusionRenameHistoryQuery.php', 'DiffusionRepositoryController' => 'applications/diffusion/controller/DiffusionRepositoryController.php', 'DiffusionRepositoryPath' => 'applications/diffusion/data/DiffusionRepositoryPath.php', 'DiffusionRepositoryTag' => 'applications/diffusion/DiffusionRepositoryTag.php', 'DiffusionRequest' => 'applications/diffusion/request/DiffusionRequest.php', 'DiffusionSetupException' => 'applications/diffusion/exception/DiffusionSetupException.php', 'DiffusionSvnBrowseQuery' => 'applications/diffusion/query/browse/DiffusionSvnBrowseQuery.php', 'DiffusionSvnCommitParentsQuery' => 'applications/diffusion/query/parents/DiffusionSvnCommitParentsQuery.php', 'DiffusionSvnCommitTagsQuery' => 'applications/diffusion/query/committags/DiffusionSvnCommitTagsQuery.php', 'DiffusionSvnContainsQuery' => 'applications/diffusion/query/contains/DiffusionSvnContainsQuery.php', 'DiffusionSvnDiffQuery' => 'applications/diffusion/query/diff/DiffusionSvnDiffQuery.php', 'DiffusionSvnExistsQuery' => 'applications/diffusion/query/exists/DiffusionSvnExistsQuery.php', 'DiffusionSvnFileContentQuery' => 'applications/diffusion/query/filecontent/DiffusionSvnFileContentQuery.php', 'DiffusionSvnHistoryQuery' => 'applications/diffusion/query/history/DiffusionSvnHistoryQuery.php', 'DiffusionSvnLastModifiedQuery' => 'applications/diffusion/query/lastmodified/DiffusionSvnLastModifiedQuery.php', 'DiffusionSvnMergedCommitsQuery' => 'applications/diffusion/query/mergedcommits/DiffusionSvnMergedCommitsQuery.php', 'DiffusionSvnRawDiffQuery' => 'applications/diffusion/query/rawdiff/DiffusionSvnRawDiffQuery.php', 'DiffusionSvnRequest' => 'applications/diffusion/request/DiffusionSvnRequest.php', 'DiffusionSvnTagListQuery' => 'applications/diffusion/query/taglist/DiffusionSvnTagListQuery.php', 'DiffusionSymbolController' => 'applications/diffusion/controller/DiffusionSymbolController.php', 'DiffusionSymbolQuery' => 'applications/diffusion/query/DiffusionSymbolQuery.php', 'DiffusionTagListController' => 'applications/diffusion/controller/DiffusionTagListController.php', 'DiffusionTagListQuery' => 'applications/diffusion/query/taglist/DiffusionTagListQuery.php', 'DiffusionTagListView' => 'applications/diffusion/view/DiffusionTagListView.php', 'DiffusionURITestCase' => 'applications/diffusion/request/__tests__/DiffusionURITestCase.php', 'DiffusionView' => 'applications/diffusion/view/DiffusionView.php', 'DivinerArticleAtomizer' => 'applications/diviner/atomizer/DivinerArticleAtomizer.php', 'DivinerAtom' => 'applications/diviner/atom/DivinerAtom.php', 'DivinerAtomCache' => 'applications/diviner/cache/DivinerAtomCache.php', 'DivinerAtomRef' => 'applications/diviner/atom/DivinerAtomRef.php', 'DivinerAtomizeWorkflow' => 'applications/diviner/workflow/DivinerAtomizeWorkflow.php', 'DivinerAtomizer' => 'applications/diviner/atomizer/DivinerAtomizer.php', 'DivinerFileAtomizer' => 'applications/diviner/atomizer/DivinerFileAtomizer.php', 'DivinerGenerateWorkflow' => 'applications/diviner/workflow/DivinerGenerateWorkflow.php', 'DivinerListController' => 'applications/diviner/controller/DivinerListController.php', 'DivinerWorkflow' => 'applications/diviner/workflow/DivinerWorkflow.php', 'DrydockAllocatorWorker' => 'applications/drydock/worker/DrydockAllocatorWorker.php', 'DrydockApacheWebrootInterface' => 'applications/drydock/interface/webroot/DrydockApacheWebrootInterface.php', 'DrydockBlueprint' => 'applications/drydock/blueprint/DrydockBlueprint.php', 'DrydockBlueprintScopeGuard' => 'applications/drydock/util/DrydockBlueprintScopeGuard.php', 'DrydockCommandInterface' => 'applications/drydock/interface/command/DrydockCommandInterface.php', 'DrydockConstants' => 'applications/drydock/constants/DrydockConstants.php', 'DrydockController' => 'applications/drydock/controller/DrydockController.php', 'DrydockDAO' => 'applications/drydock/storage/DrydockDAO.php', 'DrydockInterface' => 'applications/drydock/interface/DrydockInterface.php', 'DrydockLease' => 'applications/drydock/storage/DrydockLease.php', 'DrydockLeaseListController' => 'applications/drydock/controller/DrydockLeaseListController.php', 'DrydockLeaseQuery' => 'applications/drydock/query/DrydockLeaseQuery.php', 'DrydockLeaseReleaseController' => 'applications/drydock/controller/DrydockLeaseReleaseController.php', 'DrydockLeaseStatus' => 'applications/drydock/constants/DrydockLeaseStatus.php', 'DrydockLeaseViewController' => 'applications/drydock/controller/DrydockLeaseViewController.php', 'DrydockLocalCommandInterface' => 'applications/drydock/interface/command/DrydockLocalCommandInterface.php', 'DrydockLocalHostBlueprint' => 'applications/drydock/blueprint/DrydockLocalHostBlueprint.php', 'DrydockLog' => 'applications/drydock/storage/DrydockLog.php', 'DrydockLogController' => 'applications/drydock/controller/DrydockLogController.php', 'DrydockLogQuery' => 'applications/drydock/query/DrydockLogQuery.php', 'DrydockManagementCloseWorkflow' => 'applications/drydock/management/DrydockManagementCloseWorkflow.php', 'DrydockManagementLeaseWorkflow' => 'applications/drydock/management/DrydockManagementLeaseWorkflow.php', 'DrydockManagementReleaseWorkflow' => 'applications/drydock/management/DrydockManagementReleaseWorkflow.php', 'DrydockManagementWaitForLeaseWorkflow' => 'applications/drydock/management/DrydockManagementWaitForLeaseWorkflow.php', 'DrydockManagementWorkflow' => 'applications/drydock/management/DrydockManagementWorkflow.php', 'DrydockResource' => 'applications/drydock/storage/DrydockResource.php', 'DrydockResourceCloseController' => 'applications/drydock/controller/DrydockResourceCloseController.php', 'DrydockResourceListController' => 'applications/drydock/controller/DrydockResourceListController.php', 'DrydockResourceQuery' => 'applications/drydock/query/DrydockResourceQuery.php', 'DrydockResourceStatus' => 'applications/drydock/constants/DrydockResourceStatus.php', 'DrydockResourceViewController' => 'applications/drydock/controller/DrydockResourceViewController.php', 'DrydockSSHCommandInterface' => 'applications/drydock/interface/command/DrydockSSHCommandInterface.php', 'DrydockWebrootInterface' => 'applications/drydock/interface/webroot/DrydockWebrootInterface.php', 'DrydockWorkingCopyBlueprint' => 'applications/drydock/blueprint/DrydockWorkingCopyBlueprint.php', 'FeedPublisherWorker' => 'applications/feed/worker/FeedPublisherWorker.php', 'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php', 'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php', 'HarbormasterRunnerWorker' => 'applications/harbormaster/worker/HarbormasterRunnerWorker.php', 'HarbormasterScratchTable' => 'applications/harbormaster/storage/HarbormasterScratchTable.php', 'HeraldAction' => 'applications/herald/storage/HeraldAction.php', 'HeraldActionConfig' => 'applications/herald/config/HeraldActionConfig.php', 'HeraldApplyTranscript' => 'applications/herald/storage/transcript/HeraldApplyTranscript.php', 'HeraldCommitAdapter' => 'applications/herald/adapter/HeraldCommitAdapter.php', 'HeraldCondition' => 'applications/herald/storage/HeraldCondition.php', 'HeraldConditionConfig' => 'applications/herald/config/HeraldConditionConfig.php', 'HeraldConditionTranscript' => 'applications/herald/storage/transcript/HeraldConditionTranscript.php', 'HeraldContentTypeConfig' => 'applications/herald/config/HeraldContentTypeConfig.php', 'HeraldController' => 'applications/herald/controller/HeraldController.php', 'HeraldDAO' => 'applications/herald/storage/HeraldDAO.php', 'HeraldDeleteController' => 'applications/herald/controller/HeraldDeleteController.php', 'HeraldDifferentialRevisionAdapter' => 'applications/herald/adapter/HeraldDifferentialRevisionAdapter.php', 'HeraldDryRunAdapter' => 'applications/herald/adapter/HeraldDryRunAdapter.php', 'HeraldEditLogQuery' => 'applications/herald/query/HeraldEditLogQuery.php', 'HeraldEffect' => 'applications/herald/engine/HeraldEffect.php', 'HeraldEngine' => 'applications/herald/engine/HeraldEngine.php', 'HeraldFieldConfig' => 'applications/herald/config/HeraldFieldConfig.php', 'HeraldHomeController' => 'applications/herald/controller/HeraldHomeController.php', 'HeraldInvalidConditionException' => 'applications/herald/engine/engine/HeraldInvalidConditionException.php', 'HeraldInvalidFieldException' => 'applications/herald/engine/engine/HeraldInvalidFieldException.php', 'HeraldNewController' => 'applications/herald/controller/HeraldNewController.php', 'HeraldObjectAdapter' => 'applications/herald/adapter/HeraldObjectAdapter.php', 'HeraldObjectTranscript' => 'applications/herald/storage/transcript/HeraldObjectTranscript.php', 'HeraldRecursiveConditionsException' => 'applications/herald/engine/engine/HeraldRecursiveConditionsException.php', 'HeraldRepetitionPolicyConfig' => 'applications/herald/config/HeraldRepetitionPolicyConfig.php', 'HeraldRule' => 'applications/herald/storage/HeraldRule.php', 'HeraldRuleController' => 'applications/herald/controller/HeraldRuleController.php', 'HeraldRuleEdit' => 'applications/herald/storage/HeraldRuleEdit.php', 'HeraldRuleEditHistoryController' => 'applications/herald/controller/HeraldRuleEditHistoryController.php', 'HeraldRuleEditHistoryView' => 'applications/herald/view/HeraldRuleEditHistoryView.php', 'HeraldRuleListView' => 'applications/herald/view/HeraldRuleListView.php', 'HeraldRuleQuery' => 'applications/herald/query/HeraldRuleQuery.php', 'HeraldRuleTranscript' => 'applications/herald/storage/transcript/HeraldRuleTranscript.php', 'HeraldRuleTypeConfig' => 'applications/herald/config/HeraldRuleTypeConfig.php', 'HeraldTestConsoleController' => 'applications/herald/controller/HeraldTestConsoleController.php', 'HeraldTranscript' => 'applications/herald/storage/transcript/HeraldTranscript.php', 'HeraldTranscriptController' => 'applications/herald/controller/HeraldTranscriptController.php', 'HeraldTranscriptListController' => 'applications/herald/controller/HeraldTranscriptListController.php', 'HeraldValueTypeConfig' => 'applications/herald/config/HeraldValueTypeConfig.php', 'Javelin' => 'infrastructure/javelin/Javelin.php', 'JavelinReactorExample' => 'applications/uiexample/examples/JavelinReactorExample.php', 'JavelinUIExample' => 'applications/uiexample/examples/JavelinUIExample.php', 'JavelinViewExample' => 'applications/uiexample/examples/JavelinViewExample.php', 'JavelinViewExampleServerView' => 'applications/uiexample/examples/JavelinViewExampleServerView.php', 'LiskChunkTestCase' => 'infrastructure/storage/lisk/__tests__/LiskChunkTestCase.php', 'LiskDAO' => 'infrastructure/storage/lisk/LiskDAO.php', 'LiskDAOSet' => 'infrastructure/storage/lisk/LiskDAOSet.php', 'LiskDAOTestCase' => 'infrastructure/storage/lisk/__tests__/LiskDAOTestCase.php', 'LiskEphemeralObjectException' => 'infrastructure/storage/lisk/LiskEphemeralObjectException.php', 'LiskFixtureTestCase' => 'infrastructure/storage/lisk/__tests__/LiskFixtureTestCase.php', 'LiskIsolationTestCase' => 'infrastructure/storage/lisk/__tests__/LiskIsolationTestCase.php', 'LiskIsolationTestDAO' => 'infrastructure/storage/lisk/__tests__/LiskIsolationTestDAO.php', 'LiskIsolationTestDAOException' => 'infrastructure/storage/lisk/__tests__/LiskIsolationTestDAOException.php', 'LiskMigrationIterator' => 'infrastructure/storage/lisk/LiskMigrationIterator.php', 'ManiphestAction' => 'applications/maniphest/constants/ManiphestAction.php', 'ManiphestAuxiliaryFieldDefaultSpecification' => 'applications/maniphest/auxiliaryfield/ManiphestAuxiliaryFieldDefaultSpecification.php', 'ManiphestAuxiliaryFieldSpecification' => 'applications/maniphest/auxiliaryfield/ManiphestAuxiliaryFieldSpecification.php', 'ManiphestAuxiliaryFieldTypeException' => 'applications/maniphest/auxiliaryfield/ManiphestAuxiliaryFieldTypeException.php', 'ManiphestAuxiliaryFieldValidationException' => 'applications/maniphest/auxiliaryfield/ManiphestAuxiliaryFieldValidationException.php', 'ManiphestBatchEditController' => 'applications/maniphest/controller/ManiphestBatchEditController.php', 'ManiphestConstants' => 'applications/maniphest/constants/ManiphestConstants.php', 'ManiphestController' => 'applications/maniphest/controller/ManiphestController.php', 'ManiphestDAO' => 'applications/maniphest/storage/ManiphestDAO.php', 'ManiphestDefaultTaskExtensions' => 'applications/maniphest/extensions/ManiphestDefaultTaskExtensions.php', 'ManiphestEdgeEventListener' => 'applications/maniphest/event/ManiphestEdgeEventListener.php', 'ManiphestExportController' => 'applications/maniphest/controller/ManiphestExportController.php', 'ManiphestReplyHandler' => 'applications/maniphest/ManiphestReplyHandler.php', 'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php', 'ManiphestSavedQuery' => 'applications/maniphest/storage/ManiphestSavedQuery.php', 'ManiphestSavedQueryDeleteController' => 'applications/maniphest/controller/ManiphestSavedQueryDeleteController.php', 'ManiphestSavedQueryEditController' => 'applications/maniphest/controller/ManiphestSavedQueryEditController.php', 'ManiphestSavedQueryListController' => 'applications/maniphest/controller/ManiphestSavedQueryListController.php', 'ManiphestSearchIndexer' => 'applications/maniphest/search/ManiphestSearchIndexer.php', 'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php', 'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php', 'ManiphestTaskAuxiliaryStorage' => 'applications/maniphest/storage/ManiphestTaskAuxiliaryStorage.php', 'ManiphestTaskDescriptionChangeController' => 'applications/maniphest/controller/ManiphestTaskDescriptionChangeController.php', 'ManiphestTaskDescriptionPreviewController' => 'applications/maniphest/controller/ManiphestTaskDescriptionPreviewController.php', 'ManiphestTaskDetailController' => 'applications/maniphest/controller/ManiphestTaskDetailController.php', 'ManiphestTaskEditController' => 'applications/maniphest/controller/ManiphestTaskEditController.php', 'ManiphestTaskExtensions' => 'applications/maniphest/extensions/ManiphestTaskExtensions.php', 'ManiphestTaskListController' => 'applications/maniphest/controller/ManiphestTaskListController.php', 'ManiphestTaskListView' => 'applications/maniphest/view/ManiphestTaskListView.php', 'ManiphestTaskOwner' => 'applications/maniphest/constants/ManiphestTaskOwner.php', 'ManiphestTaskPriority' => 'applications/maniphest/constants/ManiphestTaskPriority.php', 'ManiphestTaskProject' => 'applications/maniphest/storage/ManiphestTaskProject.php', 'ManiphestTaskProjectsView' => 'applications/maniphest/view/ManiphestTaskProjectsView.php', 'ManiphestTaskQuery' => 'applications/maniphest/ManiphestTaskQuery.php', 'ManiphestTaskStatus' => 'applications/maniphest/constants/ManiphestTaskStatus.php', 'ManiphestTaskSubscriber' => 'applications/maniphest/storage/ManiphestTaskSubscriber.php', 'ManiphestTaskSummaryView' => 'applications/maniphest/view/ManiphestTaskSummaryView.php', 'ManiphestTransaction' => 'applications/maniphest/storage/ManiphestTransaction.php', 'ManiphestTransactionDetailView' => 'applications/maniphest/view/ManiphestTransactionDetailView.php', 'ManiphestTransactionEditor' => 'applications/maniphest/editor/ManiphestTransactionEditor.php', 'ManiphestTransactionListView' => 'applications/maniphest/view/ManiphestTransactionListView.php', 'ManiphestTransactionPreviewController' => 'applications/maniphest/controller/ManiphestTransactionPreviewController.php', 'ManiphestTransactionSaveController' => 'applications/maniphest/controller/ManiphestTransactionSaveController.php', 'ManiphestTransactionType' => 'applications/maniphest/constants/ManiphestTransactionType.php', 'ManiphestView' => 'applications/maniphest/view/ManiphestView.php', 'MetaMTAConstants' => 'applications/metamta/constants/MetaMTAConstants.php', 'MetaMTANotificationType' => 'applications/metamta/constants/MetaMTANotificationType.php', 'ObjectHandleLoader' => 'applications/phid/handle/ObjectHandleLoader.php', 'OwnersPackageReplyHandler' => 'applications/owners/OwnersPackageReplyHandler.php', 'PackageCreateMail' => 'applications/owners/mail/PackageCreateMail.php', 'PackageDeleteMail' => 'applications/owners/mail/PackageDeleteMail.php', 'PackageMail' => 'applications/owners/mail/PackageMail.php', 'PackageModifyMail' => 'applications/owners/mail/PackageModifyMail.php', 'Phabricator404Controller' => 'applications/base/controller/Phabricator404Controller.php', 'PhabricatorAWSConfigOptions' => 'applications/config/option/PhabricatorAWSConfigOptions.php', 'PhabricatorAccessLog' => 'infrastructure/PhabricatorAccessLog.php', 'PhabricatorAccessLogConfigOptions' => 'applications/config/option/PhabricatorAccessLogConfigOptions.php', 'PhabricatorActionListExample' => 'applications/uiexample/examples/PhabricatorActionListExample.php', 'PhabricatorActionListView' => 'view/layout/PhabricatorActionListView.php', 'PhabricatorActionView' => 'view/layout/PhabricatorActionView.php', 'PhabricatorAllCapsTranslation' => 'infrastructure/internationalization/PhabricatorAllCapsTranslation.php', 'PhabricatorAnchorView' => 'view/layout/PhabricatorAnchorView.php', 'PhabricatorApplication' => 'applications/base/PhabricatorApplication.php', 'PhabricatorApplicationApplications' => 'applications/meta/application/PhabricatorApplicationApplications.php', 'PhabricatorApplicationAudit' => 'applications/audit/application/PhabricatorApplicationAudit.php', 'PhabricatorApplicationAuth' => 'applications/auth/application/PhabricatorApplicationAuth.php', 'PhabricatorApplicationCalendar' => 'applications/calendar/application/PhabricatorApplicationCalendar.php', 'PhabricatorApplicationConduit' => 'applications/conduit/application/PhabricatorApplicationConduit.php', 'PhabricatorApplicationConfig' => 'applications/config/application/PhabricatorApplicationConfig.php', 'PhabricatorApplicationConfigOptions' => 'applications/config/option/PhabricatorApplicationConfigOptions.php', 'PhabricatorApplicationConpherence' => 'applications/conpherence/application/PhabricatorApplicationConpherence.php', 'PhabricatorApplicationCountdown' => 'applications/countdown/application/PhabricatorApplicationCountdown.php', 'PhabricatorApplicationDaemons' => 'applications/daemon/application/PhabricatorApplicationDaemons.php', 'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php', 'PhabricatorApplicationDifferential' => 'applications/differential/application/PhabricatorApplicationDifferential.php', 'PhabricatorApplicationDiffusion' => 'applications/diffusion/application/PhabricatorApplicationDiffusion.php', 'PhabricatorApplicationDiviner' => 'applications/diviner/application/PhabricatorApplicationDiviner.php', 'PhabricatorApplicationDrydock' => 'applications/drydock/application/PhabricatorApplicationDrydock.php', 'PhabricatorApplicationFact' => 'applications/fact/application/PhabricatorApplicationFact.php', 'PhabricatorApplicationFeed' => 'applications/feed/application/PhabricatorApplicationFeed.php', 'PhabricatorApplicationFiles' => 'applications/files/application/PhabricatorApplicationFiles.php', 'PhabricatorApplicationFlags' => 'applications/flag/application/PhabricatorApplicationFlags.php', 'PhabricatorApplicationHerald' => 'applications/herald/application/PhabricatorApplicationHerald.php', 'PhabricatorApplicationLaunchView' => 'applications/meta/view/PhabricatorApplicationLaunchView.php', 'PhabricatorApplicationMacro' => 'applications/macro/application/PhabricatorApplicationMacro.php', 'PhabricatorApplicationMailingLists' => 'applications/mailinglists/application/PhabricatorApplicationMailingLists.php', 'PhabricatorApplicationManiphest' => 'applications/maniphest/application/PhabricatorApplicationManiphest.php', 'PhabricatorApplicationMetaMTA' => 'applications/metamta/application/PhabricatorApplicationMetaMTA.php', 'PhabricatorApplicationOwners' => 'applications/owners/application/PhabricatorApplicationOwners.php', 'PhabricatorApplicationPHID' => 'applications/phid/application/PhabricatorApplicationPHID.php', 'PhabricatorApplicationPHPAST' => 'applications/phpast/application/PhabricatorApplicationPHPAST.php', 'PhabricatorApplicationPaste' => 'applications/paste/application/PhabricatorApplicationPaste.php', 'PhabricatorApplicationPeople' => 'applications/people/application/PhabricatorApplicationPeople.php', 'PhabricatorApplicationPhame' => 'applications/phame/application/PhabricatorApplicationPhame.php', 'PhabricatorApplicationPholio' => 'applications/pholio/application/PhabricatorApplicationPholio.php', 'PhabricatorApplicationPhriction' => 'applications/phriction/application/PhabricatorApplicationPhriction.php', 'PhabricatorApplicationPonder' => 'applications/ponder/application/PhabricatorApplicationPonder.php', 'PhabricatorApplicationProject' => 'applications/project/application/PhabricatorApplicationProject.php', 'PhabricatorApplicationRepositories' => 'applications/repository/application/PhabricatorApplicationRepositories.php', 'PhabricatorApplicationSettings' => 'applications/settings/application/PhabricatorApplicationSettings.php', 'PhabricatorApplicationSlowvote' => 'applications/slowvote/application/PhabricatorApplicationSlowvote.php', 'PhabricatorApplicationStatusView' => 'applications/meta/view/PhabricatorApplicationStatusView.php', 'PhabricatorApplicationSubscriptions' => 'applications/subscriptions/application/PhabricatorApplicationSubscriptions.php', 'PhabricatorApplicationTransaction' => 'applications/transactions/storage/PhabricatorApplicationTransaction.php', 'PhabricatorApplicationTransactionComment' => 'applications/transactions/storage/PhabricatorApplicationTransactionComment.php', 'PhabricatorApplicationTransactionCommentEditController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php', 'PhabricatorApplicationTransactionCommentEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php', 'PhabricatorApplicationTransactionCommentHistoryController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentHistoryController.php', 'PhabricatorApplicationTransactionCommentQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php', 'PhabricatorApplicationTransactionCommentView' => 'applications/transactions/view/PhabricatorApplicationTransactionCommentView.php', 'PhabricatorApplicationTransactionController' => 'applications/transactions/controller/PhabricatorApplicationTransactionController.php', 'PhabricatorApplicationTransactionEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionEditor.php', 'PhabricatorApplicationTransactionFeedStory' => 'applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php', 'PhabricatorApplicationTransactionNoEffectException' => 'applications/transactions/exception/PhabricatorApplicationTransactionNoEffectException.php', 'PhabricatorApplicationTransactionNoEffectResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionNoEffectResponse.php', 'PhabricatorApplicationTransactionQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionQuery.php', 'PhabricatorApplicationTransactionResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionResponse.php', 'PhabricatorApplicationTransactionView' => 'applications/transactions/view/PhabricatorApplicationTransactionView.php', 'PhabricatorApplicationTransactions' => 'applications/transactions/application/PhabricatorApplicationTransactions.php', 'PhabricatorApplicationUIExamples' => 'applications/uiexample/application/PhabricatorApplicationUIExamples.php', 'PhabricatorApplicationUninstallController' => 'applications/meta/controller/PhabricatorApplicationUninstallController.php', 'PhabricatorApplicationsController' => 'applications/meta/controller/PhabricatorApplicationsController.php', 'PhabricatorApplicationsListController' => 'applications/meta/controller/PhabricatorApplicationsListController.php', 'PhabricatorAuditActionConstants' => 'applications/audit/constants/PhabricatorAuditActionConstants.php', 'PhabricatorAuditAddCommentController' => 'applications/audit/controller/PhabricatorAuditAddCommentController.php', 'PhabricatorAuditComment' => 'applications/audit/storage/PhabricatorAuditComment.php', 'PhabricatorAuditCommentEditor' => 'applications/audit/editor/PhabricatorAuditCommentEditor.php', 'PhabricatorAuditCommitListView' => 'applications/audit/view/PhabricatorAuditCommitListView.php', 'PhabricatorAuditCommitQuery' => 'applications/audit/query/PhabricatorAuditCommitQuery.php', 'PhabricatorAuditCommitStatusConstants' => 'applications/audit/constants/PhabricatorAuditCommitStatusConstants.php', 'PhabricatorAuditController' => 'applications/audit/controller/PhabricatorAuditController.php', 'PhabricatorAuditDAO' => 'applications/audit/storage/PhabricatorAuditDAO.php', 'PhabricatorAuditInlineComment' => 'applications/audit/storage/PhabricatorAuditInlineComment.php', 'PhabricatorAuditListController' => 'applications/audit/controller/PhabricatorAuditListController.php', 'PhabricatorAuditListView' => 'applications/audit/view/PhabricatorAuditListView.php', 'PhabricatorAuditPreviewController' => 'applications/audit/controller/PhabricatorAuditPreviewController.php', 'PhabricatorAuditQuery' => 'applications/audit/query/PhabricatorAuditQuery.php', 'PhabricatorAuditReplyHandler' => 'applications/audit/PhabricatorAuditReplyHandler.php', 'PhabricatorAuditStatusConstants' => 'applications/audit/constants/PhabricatorAuditStatusConstants.php', 'PhabricatorAuthController' => 'applications/auth/controller/PhabricatorAuthController.php', 'PhabricatorAuthenticationConfigOptions' => 'applications/config/option/PhabricatorAuthenticationConfigOptions.php', 'PhabricatorBarePageExample' => 'applications/uiexample/examples/PhabricatorBarePageExample.php', 'PhabricatorBarePageView' => 'view/page/PhabricatorBarePageView.php', 'PhabricatorBaseEnglishTranslation' => 'infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php', 'PhabricatorBuiltinPatchList' => 'infrastructure/storage/patch/PhabricatorBuiltinPatchList.php', 'PhabricatorButtonsExample' => 'applications/uiexample/examples/PhabricatorButtonsExample.php', 'PhabricatorCacheDAO' => 'applications/cache/storage/PhabricatorCacheDAO.php', 'PhabricatorCaches' => 'applications/cache/PhabricatorCaches.php', 'PhabricatorCalendarBrowseController' => 'applications/calendar/controller/PhabricatorCalendarBrowseController.php', 'PhabricatorCalendarController' => 'applications/calendar/controller/PhabricatorCalendarController.php', 'PhabricatorCalendarDAO' => 'applications/calendar/storage/PhabricatorCalendarDAO.php', 'PhabricatorCalendarDeleteStatusController' => 'applications/calendar/controller/PhabricatorCalendarDeleteStatusController.php', 'PhabricatorCalendarEditStatusController' => 'applications/calendar/controller/PhabricatorCalendarEditStatusController.php', 'PhabricatorCalendarHoliday' => 'applications/calendar/storage/PhabricatorCalendarHoliday.php', 'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php', 'PhabricatorCalendarViewStatusController' => 'applications/calendar/controller/PhabricatorCalendarViewStatusController.php', 'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php', 'PhabricatorChatLogChannelListController' => 'applications/chatlog/controller/PhabricatorChatLogChannelListController.php', 'PhabricatorChatLogChannelLogController' => 'applications/chatlog/controller/PhabricatorChatLogChannelLogController.php', 'PhabricatorChatLogConstants' => 'applications/chatlog/constants/PhabricatorChatLogConstants.php', 'PhabricatorChatLogController' => 'applications/chatlog/controller/PhabricatorChatLogController.php', 'PhabricatorChatLogDAO' => 'applications/chatlog/storage/PhabricatorChatLogDAO.php', 'PhabricatorChatLogEvent' => 'applications/chatlog/storage/PhabricatorChatLogEvent.php', 'PhabricatorChatLogEventType' => 'applications/chatlog/constants/PhabricatorChatLogEventType.php', 'PhabricatorChatLogQuery' => 'applications/chatlog/PhabricatorChatLogQuery.php', 'PhabricatorConduitAPIController' => 'applications/conduit/controller/PhabricatorConduitAPIController.php', 'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/PhabricatorConduitCertificateToken.php', 'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/PhabricatorConduitConnectionLog.php', 'PhabricatorConduitConsoleController' => 'applications/conduit/controller/PhabricatorConduitConsoleController.php', 'PhabricatorConduitController' => 'applications/conduit/controller/PhabricatorConduitController.php', 'PhabricatorConduitDAO' => 'applications/conduit/storage/PhabricatorConduitDAO.php', 'PhabricatorConduitListController' => 'applications/conduit/controller/PhabricatorConduitListController.php', 'PhabricatorConduitLogController' => 'applications/conduit/controller/PhabricatorConduitLogController.php', 'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/PhabricatorConduitMethodCallLog.php', 'PhabricatorConduitTokenController' => 'applications/conduit/controller/PhabricatorConduitTokenController.php', 'PhabricatorConfigAllController' => 'applications/config/controller/PhabricatorConfigAllController.php', 'PhabricatorConfigController' => 'applications/config/controller/PhabricatorConfigController.php', 'PhabricatorConfigDatabaseSource' => 'infrastructure/env/PhabricatorConfigDatabaseSource.php', 'PhabricatorConfigDefaultSource' => 'infrastructure/env/PhabricatorConfigDefaultSource.php', 'PhabricatorConfigDictionarySource' => 'infrastructure/env/PhabricatorConfigDictionarySource.php', 'PhabricatorConfigEditController' => 'applications/config/controller/PhabricatorConfigEditController.php', 'PhabricatorConfigEditor' => 'applications/config/editor/PhabricatorConfigEditor.php', 'PhabricatorConfigEntry' => 'applications/config/storage/PhabricatorConfigEntry.php', 'PhabricatorConfigEntryDAO' => 'applications/config/storage/PhabricatorConfigEntryDAO.php', 'PhabricatorConfigFileSource' => 'infrastructure/env/PhabricatorConfigFileSource.php', 'PhabricatorConfigGroupController' => 'applications/config/controller/PhabricatorConfigGroupController.php', 'PhabricatorConfigIssueListController' => 'applications/config/controller/PhabricatorConfigIssueListController.php', 'PhabricatorConfigIssueViewController' => 'applications/config/controller/PhabricatorConfigIssueViewController.php', 'PhabricatorConfigJSON' => 'applications/config/json/PhabricatorConfigJSON.php', 'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php', 'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php', 'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php', 'PhabricatorConfigManagementGetWorkflow' => 'applications/config/management/PhabricatorConfigManagementGetWorkflow.php', 'PhabricatorConfigManagementListWorkflow' => 'applications/config/management/PhabricatorConfigManagementListWorkflow.php', 'PhabricatorConfigManagementSetWorkflow' => 'applications/config/management/PhabricatorConfigManagementSetWorkflow.php', 'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php', 'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php', 'PhabricatorConfigProxySource' => 'infrastructure/env/PhabricatorConfigProxySource.php', 'PhabricatorConfigResponse' => 'applications/config/response/PhabricatorConfigResponse.php', 'PhabricatorConfigSource' => 'infrastructure/env/PhabricatorConfigSource.php', 'PhabricatorConfigStackSource' => 'infrastructure/env/PhabricatorConfigStackSource.php', 'PhabricatorConfigTransaction' => 'applications/config/storage/PhabricatorConfigTransaction.php', 'PhabricatorConfigTransactionQuery' => 'applications/config/query/PhabricatorConfigTransactionQuery.php', 'PhabricatorConfigValidationException' => 'applications/config/exception/PhabricatorConfigValidationException.php', 'PhabricatorContentSource' => 'applications/metamta/contentsource/PhabricatorContentSource.php', 'PhabricatorContentSourceView' => 'applications/metamta/contentsource/PhabricatorContentSourceView.php', 'PhabricatorController' => 'applications/base/controller/PhabricatorController.php', 'PhabricatorCoreConfigOptions' => 'applications/config/option/PhabricatorCoreConfigOptions.php', 'PhabricatorCountdownController' => 'applications/countdown/controller/PhabricatorCountdownController.php', 'PhabricatorCountdownDAO' => 'applications/countdown/storage/PhabricatorCountdownDAO.php', 'PhabricatorCountdownDeleteController' => 'applications/countdown/controller/PhabricatorCountdownDeleteController.php', 'PhabricatorCountdownEditController' => 'applications/countdown/controller/PhabricatorCountdownEditController.php', 'PhabricatorCountdownListController' => 'applications/countdown/controller/PhabricatorCountdownListController.php', 'PhabricatorCountdownViewController' => 'applications/countdown/controller/PhabricatorCountdownViewController.php', 'PhabricatorCrumbView' => 'view/layout/PhabricatorCrumbView.php', 'PhabricatorCrumbsView' => 'view/layout/PhabricatorCrumbsView.php', 'PhabricatorCursorPagedPolicyAwareQuery' => 'infrastructure/query/policy/PhabricatorCursorPagedPolicyAwareQuery.php', 'PhabricatorDaemon' => 'infrastructure/daemon/PhabricatorDaemon.php', 'PhabricatorDaemonCombinedLogController' => 'applications/daemon/controller/PhabricatorDaemonCombinedLogController.php', 'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/PhabricatorDaemonConsoleController.php', 'PhabricatorDaemonControl' => 'infrastructure/daemon/PhabricatorDaemonControl.php', 'PhabricatorDaemonController' => 'applications/daemon/controller/PhabricatorDaemonController.php', 'PhabricatorDaemonDAO' => 'infrastructure/daemon/storage/PhabricatorDaemonDAO.php', 'PhabricatorDaemonLog' => 'infrastructure/daemon/storage/PhabricatorDaemonLog.php', 'PhabricatorDaemonLogEvent' => 'infrastructure/daemon/storage/PhabricatorDaemonLogEvent.php', 'PhabricatorDaemonLogEventsView' => 'applications/daemon/view/PhabricatorDaemonLogEventsView.php', 'PhabricatorDaemonLogListController' => 'applications/daemon/controller/PhabricatorDaemonLogListController.php', 'PhabricatorDaemonLogListView' => 'applications/daemon/view/PhabricatorDaemonLogListView.php', 'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/PhabricatorDaemonLogViewController.php', 'PhabricatorDaemonReference' => 'infrastructure/daemon/control/PhabricatorDaemonReference.php', 'PhabricatorDefaultFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorDefaultFileStorageEngineSelector.php', 'PhabricatorDefaultSearchEngineSelector' => 'applications/search/selector/PhabricatorDefaultSearchEngineSelector.php', 'PhabricatorDeveloperConfigOptions' => 'applications/config/option/PhabricatorDeveloperConfigOptions.php', 'PhabricatorDifferenceEngine' => 'infrastructure/diff/PhabricatorDifferenceEngine.php', 'PhabricatorDifferentialConfigOptions' => 'applications/differential/config/PhabricatorDifferentialConfigOptions.php', 'PhabricatorDiffusionConfigOptions' => 'applications/diffusion/config/PhabricatorDiffusionConfigOptions.php', 'PhabricatorDirectoryController' => 'applications/directory/controller/PhabricatorDirectoryController.php', 'PhabricatorDirectoryMainController' => 'applications/directory/controller/PhabricatorDirectoryMainController.php', 'PhabricatorDisabledUserController' => 'applications/auth/controller/PhabricatorDisabledUserController.php', 'PhabricatorDisqusConfigOptions' => 'applications/config/option/PhabricatorDisqusConfigOptions.php', 'PhabricatorDraft' => 'applications/draft/storage/PhabricatorDraft.php', 'PhabricatorDraftDAO' => 'applications/draft/storage/PhabricatorDraftDAO.php', 'PhabricatorEdgeConfig' => 'infrastructure/edges/constants/PhabricatorEdgeConfig.php', 'PhabricatorEdgeConstants' => 'infrastructure/edges/constants/PhabricatorEdgeConstants.php', 'PhabricatorEdgeCycleException' => 'infrastructure/edges/exception/PhabricatorEdgeCycleException.php', 'PhabricatorEdgeEditor' => 'infrastructure/edges/editor/PhabricatorEdgeEditor.php', 'PhabricatorEdgeGraph' => 'infrastructure/edges/util/PhabricatorEdgeGraph.php', 'PhabricatorEdgeQuery' => 'infrastructure/edges/query/PhabricatorEdgeQuery.php', 'PhabricatorEdgeTestCase' => 'infrastructure/edges/__tests__/PhabricatorEdgeTestCase.php', 'PhabricatorEditor' => 'infrastructure/PhabricatorEditor.php', 'PhabricatorEmailLoginController' => 'applications/auth/controller/PhabricatorEmailLoginController.php', 'PhabricatorEmailTokenController' => 'applications/auth/controller/PhabricatorEmailTokenController.php', 'PhabricatorEmailVerificationController' => 'applications/people/controller/PhabricatorEmailVerificationController.php', 'PhabricatorEnglishTranslation' => 'infrastructure/internationalization/PhabricatorEnglishTranslation.php', 'PhabricatorEnv' => 'infrastructure/env/PhabricatorEnv.php', 'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__/PhabricatorEnvTestCase.php', 'PhabricatorErrorExample' => 'applications/uiexample/examples/PhabricatorErrorExample.php', 'PhabricatorEvent' => 'infrastructure/events/PhabricatorEvent.php', 'PhabricatorEventEngine' => 'infrastructure/events/PhabricatorEventEngine.php', 'PhabricatorEventType' => 'infrastructure/events/constant/PhabricatorEventType.php', 'PhabricatorExampleEventListener' => 'infrastructure/events/PhabricatorExampleEventListener.php', 'PhabricatorExtendingPhabricatorConfigOptions' => 'applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php', 'PhabricatorFacebookConfigOptions' => 'applications/config/option/PhabricatorFacebookConfigOptions.php', 'PhabricatorFactAggregate' => 'applications/fact/storage/PhabricatorFactAggregate.php', 'PhabricatorFactChartController' => 'applications/fact/controller/PhabricatorFactChartController.php', 'PhabricatorFactController' => 'applications/fact/controller/PhabricatorFactController.php', 'PhabricatorFactCountEngine' => 'applications/fact/engine/PhabricatorFactCountEngine.php', 'PhabricatorFactCursor' => 'applications/fact/storage/PhabricatorFactCursor.php', 'PhabricatorFactDAO' => 'applications/fact/storage/PhabricatorFactDAO.php', 'PhabricatorFactDaemon' => 'applications/fact/daemon/PhabricatorFactDaemon.php', 'PhabricatorFactEngine' => 'applications/fact/engine/PhabricatorFactEngine.php', 'PhabricatorFactHomeController' => 'applications/fact/controller/PhabricatorFactHomeController.php', 'PhabricatorFactLastUpdatedEngine' => 'applications/fact/engine/PhabricatorFactLastUpdatedEngine.php', 'PhabricatorFactManagementAnalyzeWorkflow' => 'applications/fact/management/PhabricatorFactManagementAnalyzeWorkflow.php', 'PhabricatorFactManagementCursorsWorkflow' => 'applications/fact/management/PhabricatorFactManagementCursorsWorkflow.php', 'PhabricatorFactManagementDestroyWorkflow' => 'applications/fact/management/PhabricatorFactManagementDestroyWorkflow.php', 'PhabricatorFactManagementListWorkflow' => 'applications/fact/management/PhabricatorFactManagementListWorkflow.php', 'PhabricatorFactManagementStatusWorkflow' => 'applications/fact/management/PhabricatorFactManagementStatusWorkflow.php', 'PhabricatorFactManagementWorkflow' => 'applications/fact/management/PhabricatorFactManagementWorkflow.php', 'PhabricatorFactRaw' => 'applications/fact/storage/PhabricatorFactRaw.php', 'PhabricatorFactSimpleSpec' => 'applications/fact/spec/PhabricatorFactSimpleSpec.php', 'PhabricatorFactSpec' => 'applications/fact/spec/PhabricatorFactSpec.php', 'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php', 'PhabricatorFeedBuilder' => 'applications/feed/builder/PhabricatorFeedBuilder.php', 'PhabricatorFeedConfigOptions' => 'applications/feed/config/PhabricatorFeedConfigOptions.php', 'PhabricatorFeedConstants' => 'applications/feed/constants/PhabricatorFeedConstants.php', 'PhabricatorFeedController' => 'applications/feed/controller/PhabricatorFeedController.php', 'PhabricatorFeedDAO' => 'applications/feed/storage/PhabricatorFeedDAO.php', 'PhabricatorFeedMainController' => 'applications/feed/controller/PhabricatorFeedMainController.php', 'PhabricatorFeedPublicStreamController' => 'applications/feed/controller/PhabricatorFeedPublicStreamController.php', 'PhabricatorFeedQuery' => 'applications/feed/PhabricatorFeedQuery.php', 'PhabricatorFeedStory' => 'applications/feed/story/PhabricatorFeedStory.php', 'PhabricatorFeedStoryAggregate' => 'applications/feed/story/PhabricatorFeedStoryAggregate.php', 'PhabricatorFeedStoryAudit' => 'applications/feed/story/PhabricatorFeedStoryAudit.php', 'PhabricatorFeedStoryCommit' => 'applications/feed/story/PhabricatorFeedStoryCommit.php', 'PhabricatorFeedStoryData' => 'applications/feed/storage/PhabricatorFeedStoryData.php', 'PhabricatorFeedStoryDifferential' => 'applications/feed/story/PhabricatorFeedStoryDifferential.php', 'PhabricatorFeedStoryDifferentialAggregate' => 'applications/feed/story/PhabricatorFeedStoryDifferentialAggregate.php', 'PhabricatorFeedStoryManiphest' => 'applications/feed/story/PhabricatorFeedStoryManiphest.php', 'PhabricatorFeedStoryManiphestAggregate' => 'applications/feed/story/PhabricatorFeedStoryManiphestAggregate.php', 'PhabricatorFeedStoryNotification' => 'applications/notification/storage/PhabricatorFeedStoryNotification.php', 'PhabricatorFeedStoryPhriction' => 'applications/feed/story/PhabricatorFeedStoryPhriction.php', 'PhabricatorFeedStoryProject' => 'applications/feed/story/PhabricatorFeedStoryProject.php', 'PhabricatorFeedStoryPublisher' => 'applications/feed/PhabricatorFeedStoryPublisher.php', 'PhabricatorFeedStoryReference' => 'applications/feed/storage/PhabricatorFeedStoryReference.php', 'PhabricatorFeedStoryStatus' => 'applications/feed/story/PhabricatorFeedStoryStatus.php', 'PhabricatorFeedStoryTypeConstants' => 'applications/feed/constants/PhabricatorFeedStoryTypeConstants.php', 'PhabricatorFeedStoryView' => 'applications/feed/view/PhabricatorFeedStoryView.php', 'PhabricatorFeedView' => 'applications/feed/view/PhabricatorFeedView.php', 'PhabricatorFile' => 'applications/files/storage/PhabricatorFile.php', 'PhabricatorFileController' => 'applications/files/controller/PhabricatorFileController.php', 'PhabricatorFileDAO' => 'applications/files/storage/PhabricatorFileDAO.php', 'PhabricatorFileDataController' => 'applications/files/controller/PhabricatorFileDataController.php', 'PhabricatorFileDeleteController' => 'applications/files/controller/PhabricatorFileDeleteController.php', 'PhabricatorFileDropUploadController' => 'applications/files/controller/PhabricatorFileDropUploadController.php', 'PhabricatorFileImageMacro' => 'applications/macro/storage/PhabricatorFileImageMacro.php', 'PhabricatorFileInfoController' => 'applications/files/controller/PhabricatorFileInfoController.php', 'PhabricatorFileLinkListView' => 'view/layout/PhabricatorFileLinkListView.php', 'PhabricatorFileLinkView' => 'view/layout/PhabricatorFileLinkView.php', 'PhabricatorFileListController' => 'applications/files/controller/PhabricatorFileListController.php', 'PhabricatorFileQuery' => 'applications/files/query/PhabricatorFileQuery.php', 'PhabricatorFileShortcutController' => 'applications/files/controller/PhabricatorFileShortcutController.php', 'PhabricatorFileStorageBlob' => 'applications/files/storage/PhabricatorFileStorageBlob.php', 'PhabricatorFileStorageConfigurationException' => 'applications/files/exception/PhabricatorFileStorageConfigurationException.php', 'PhabricatorFileStorageEngine' => 'applications/files/engine/PhabricatorFileStorageEngine.php', 'PhabricatorFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorFileStorageEngineSelector.php', 'PhabricatorFileTransformController' => 'applications/files/controller/PhabricatorFileTransformController.php', 'PhabricatorFileUploadController' => 'applications/files/controller/PhabricatorFileUploadController.php', 'PhabricatorFileUploadException' => 'applications/files/exception/PhabricatorFileUploadException.php', 'PhabricatorFilesConfigOptions' => 'applications/files/config/PhabricatorFilesConfigOptions.php', 'PhabricatorFilesManagementEnginesWorkflow' => 'applications/files/management/PhabricatorFilesManagementEnginesWorkflow.php', 'PhabricatorFilesManagementMetadataWorkflow' => 'applications/files/management/PhabricatorFilesManagementMetadataWorkflow.php', 'PhabricatorFilesManagementMigrateWorkflow' => 'applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php', 'PhabricatorFilesManagementWorkflow' => 'applications/files/management/PhabricatorFilesManagementWorkflow.php', 'PhabricatorFlag' => 'applications/flag/storage/PhabricatorFlag.php', 'PhabricatorFlagColor' => 'applications/flag/constants/PhabricatorFlagColor.php', 'PhabricatorFlagConstants' => 'applications/flag/constants/PhabricatorFlagConstants.php', 'PhabricatorFlagController' => 'applications/flag/controller/PhabricatorFlagController.php', 'PhabricatorFlagDAO' => 'applications/flag/storage/PhabricatorFlagDAO.php', 'PhabricatorFlagDeleteController' => 'applications/flag/controller/PhabricatorFlagDeleteController.php', 'PhabricatorFlagEditController' => 'applications/flag/controller/PhabricatorFlagEditController.php', 'PhabricatorFlagListController' => 'applications/flag/controller/PhabricatorFlagListController.php', 'PhabricatorFlagListView' => 'applications/flag/view/PhabricatorFlagListView.php', 'PhabricatorFlagQuery' => 'applications/flag/query/PhabricatorFlagQuery.php', 'PhabricatorFlagsUIEventListener' => 'applications/flag/events/PhabricatorFlagsUIEventListener.php', 'PhabricatorFormExample' => 'applications/uiexample/examples/PhabricatorFormExample.php', 'PhabricatorGarbageCollectorConfigOptions' => 'applications/config/option/PhabricatorGarbageCollectorConfigOptions.php', 'PhabricatorGarbageCollectorDaemon' => 'infrastructure/daemon/PhabricatorGarbageCollectorDaemon.php', 'PhabricatorGitGraphStream' => 'applications/repository/daemon/PhabricatorGitGraphStream.php', 'PhabricatorGitHubConfigOptions' => 'applications/config/option/PhabricatorGitHubConfigOptions.php', 'PhabricatorGlobalLock' => 'infrastructure/util/PhabricatorGlobalLock.php', 'PhabricatorGlobalUploadTargetView' => 'applications/files/view/PhabricatorGlobalUploadTargetView.php', 'PhabricatorGoogleConfigOptions' => 'applications/config/option/PhabricatorGoogleConfigOptions.php', 'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/PhabricatorHandleObjectSelectorDataView.php', 'PhabricatorHash' => 'infrastructure/util/PhabricatorHash.php', 'PhabricatorHashTestCase' => 'infrastructure/util/__tests__/PhabricatorHashTestCase.php', 'PhabricatorHeaderView' => 'view/layout/PhabricatorHeaderView.php', 'PhabricatorHelpController' => 'applications/help/controller/PhabricatorHelpController.php', 'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php', 'PhabricatorIRCBot' => 'infrastructure/daemon/irc/PhabricatorIRCBot.php', 'PhabricatorIRCDifferentialNotificationHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCDifferentialNotificationHandler.php', 'PhabricatorIRCFeedNotificationHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCFeedNotificationHandler.php', 'PhabricatorIRCHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCHandler.php', 'PhabricatorIRCLogHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCLogHandler.php', 'PhabricatorIRCMacroHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCMacroHandler.php', 'PhabricatorIRCMessage' => 'infrastructure/daemon/irc/PhabricatorIRCMessage.php', 'PhabricatorIRCObjectNameHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCObjectNameHandler.php', 'PhabricatorIRCProtocolHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCProtocolHandler.php', 'PhabricatorIRCSymbolHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCSymbolHandler.php', 'PhabricatorIRCWhatsNewHandler' => 'infrastructure/daemon/irc/handler/PhabricatorIRCWhatsNewHandler.php', 'PhabricatorImageTransformer' => 'applications/files/PhabricatorImageTransformer.php', 'PhabricatorInfrastructureTestCase' => 'infrastructure/__tests__/PhabricatorInfrastructureTestCase.php', 'PhabricatorInlineCommentController' => 'infrastructure/diff/PhabricatorInlineCommentController.php', 'PhabricatorInlineCommentInterface' => 'infrastructure/diff/interface/PhabricatorInlineCommentInterface.php', 'PhabricatorInlineCommentPreviewController' => 'infrastructure/diff/PhabricatorInlineCommentPreviewController.php', 'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php', 'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php', 'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php', 'PhabricatorKeyValueDatabaseCache' => 'applications/cache/PhabricatorKeyValueDatabaseCache.php', 'PhabricatorLDAPConfigOptions' => 'applications/config/option/PhabricatorLDAPConfigOptions.php', 'PhabricatorLDAPLoginController' => 'applications/auth/controller/PhabricatorLDAPLoginController.php', 'PhabricatorLDAPProvider' => 'applications/auth/ldap/PhabricatorLDAPProvider.php', 'PhabricatorLDAPRegistrationController' => 'applications/auth/controller/PhabricatorLDAPRegistrationController.php', 'PhabricatorLDAPUnknownUserException' => 'applications/auth/ldap/PhabricatorLDAPUnknownUserException.php', 'PhabricatorLDAPUnlinkController' => 'applications/auth/controller/PhabricatorLDAPUnlinkController.php', 'PhabricatorLintEngine' => 'infrastructure/lint/PhabricatorLintEngine.php', 'PhabricatorLiskDAO' => 'infrastructure/storage/lisk/PhabricatorLiskDAO.php', 'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php', 'PhabricatorLocalTimeTestCase' => 'view/__tests__/PhabricatorLocalTimeTestCase.php', 'PhabricatorLoginController' => 'applications/auth/controller/PhabricatorLoginController.php', 'PhabricatorLoginValidateController' => 'applications/auth/controller/PhabricatorLoginValidateController.php', 'PhabricatorLogoutController' => 'applications/auth/controller/PhabricatorLogoutController.php', 'PhabricatorMacroCommentController' => 'applications/macro/controller/PhabricatorMacroCommentController.php', 'PhabricatorMacroConfigOptions' => 'applications/macro/config/PhabricatorMacroConfigOptions.php', 'PhabricatorMacroController' => 'applications/macro/controller/PhabricatorMacroController.php', 'PhabricatorMacroDisableController' => 'applications/macro/controller/PhabricatorMacroDisableController.php', 'PhabricatorMacroEditController' => 'applications/macro/controller/PhabricatorMacroEditController.php', 'PhabricatorMacroEditor' => 'applications/macro/editor/PhabricatorMacroEditor.php', 'PhabricatorMacroListController' => 'applications/macro/controller/PhabricatorMacroListController.php', 'PhabricatorMacroMemeController' => 'applications/macro/controller/PhabricatorMacroMemeController.php', 'PhabricatorMacroMemeDialogController' => 'applications/macro/controller/PhabricatorMacroMemeDialogController.php', 'PhabricatorMacroReplyHandler' => 'applications/macro/mail/PhabricatorMacroReplyHandler.php', 'PhabricatorMacroTransaction' => 'applications/macro/storage/PhabricatorMacroTransaction.php', 'PhabricatorMacroTransactionComment' => 'applications/macro/storage/PhabricatorMacroTransactionComment.php', 'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php', 'PhabricatorMacroTransactionType' => 'applications/macro/constants/PhabricatorMacroTransactionType.php', 'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php', 'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAdapter.php', 'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAmazonSESAdapter.php', 'PhabricatorMailImplementationPHPMailerAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php', 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php', 'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php', 'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php', 'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php', 'PhabricatorMailingListsController' => 'applications/mailinglists/controller/PhabricatorMailingListsController.php', 'PhabricatorMailingListsEditController' => 'applications/mailinglists/controller/PhabricatorMailingListsEditController.php', 'PhabricatorMailingListsListController' => 'applications/mailinglists/controller/PhabricatorMailingListsListController.php', 'PhabricatorMainMenuGroupView' => 'view/page/menu/PhabricatorMainMenuGroupView.php', 'PhabricatorMainMenuIconView' => 'view/page/menu/PhabricatorMainMenuIconView.php', 'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php', 'PhabricatorMainMenuView' => 'view/page/menu/PhabricatorMainMenuView.php', 'PhabricatorManiphestConfigOptions' => 'applications/maniphest/config/PhabricatorManiphestConfigOptions.php', 'PhabricatorMarkupCache' => 'applications/cache/storage/PhabricatorMarkupCache.php', 'PhabricatorMarkupEngine' => 'infrastructure/markup/PhabricatorMarkupEngine.php', 'PhabricatorMarkupInterface' => 'infrastructure/markup/PhabricatorMarkupInterface.php', 'PhabricatorMenuItemView' => 'view/layout/PhabricatorMenuItemView.php', 'PhabricatorMenuView' => 'view/layout/PhabricatorMenuView.php', + 'PhabricatorMenuViewTestCase' => 'view/layout/__tests__/PhabricatorMenuViewTestCase.php', 'PhabricatorMercurialGraphStream' => 'applications/repository/daemon/PhabricatorMercurialGraphStream.php', 'PhabricatorMetaMTAAttachment' => 'applications/metamta/storage/PhabricatorMetaMTAAttachment.php', 'PhabricatorMetaMTAConfigOptions' => 'applications/config/option/PhabricatorMetaMTAConfigOptions.php', 'PhabricatorMetaMTAController' => 'applications/metamta/controller/PhabricatorMetaMTAController.php', 'PhabricatorMetaMTADAO' => 'applications/metamta/storage/PhabricatorMetaMTADAO.php', 'PhabricatorMetaMTAEmailBodyParser' => 'applications/metamta/PhabricatorMetaMTAEmailBodyParser.php', 'PhabricatorMetaMTAEmailBodyParserTestCase' => 'applications/metamta/__tests__/PhabricatorMetaMTAEmailBodyParserTestCase.php', 'PhabricatorMetaMTAListController' => 'applications/metamta/controller/PhabricatorMetaMTAListController.php', 'PhabricatorMetaMTAMail' => 'applications/metamta/storage/PhabricatorMetaMTAMail.php', 'PhabricatorMetaMTAMailBody' => 'applications/metamta/view/PhabricatorMetaMTAMailBody.php', 'PhabricatorMetaMTAMailBodyTestCase' => 'applications/metamta/view/__tests__/PhabricatorMetaMTAMailBodyTestCase.php', 'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php', 'PhabricatorMetaMTAMailingList' => 'applications/mailinglists/storage/PhabricatorMetaMTAMailingList.php', 'PhabricatorMetaMTAReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTAReceiveController.php', 'PhabricatorMetaMTAReceivedListController' => 'applications/metamta/controller/PhabricatorMetaMTAReceivedListController.php', 'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php', 'PhabricatorMetaMTASendController' => 'applications/metamta/controller/PhabricatorMetaMTASendController.php', 'PhabricatorMetaMTASendGridReceiveController' => 'applications/metamta/controller/PhabricatorMetaMTASendGridReceiveController.php', 'PhabricatorMetaMTAViewController' => 'applications/metamta/controller/PhabricatorMetaMTAViewController.php', 'PhabricatorMetaMTAWorker' => 'applications/metamta/PhabricatorMetaMTAWorker.php', 'PhabricatorMustVerifyEmailController' => 'applications/auth/controller/PhabricatorMustVerifyEmailController.php', 'PhabricatorMySQLConfigOptions' => 'applications/config/option/PhabricatorMySQLConfigOptions.php', 'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/PhabricatorMySQLFileStorageEngine.php', 'PhabricatorNotificationBuilder' => 'applications/notification/builder/PhabricatorNotificationBuilder.php', 'PhabricatorNotificationClearController' => 'applications/notification/controller/PhabricatorNotificationClearController.php', 'PhabricatorNotificationConfigOptions' => 'applications/config/option/PhabricatorNotificationConfigOptions.php', 'PhabricatorNotificationController' => 'applications/notification/controller/PhabricatorNotificationController.php', 'PhabricatorNotificationIndividualController' => 'applications/notification/controller/PhabricatorNotificationIndividualController.php', 'PhabricatorNotificationListController' => 'applications/notification/controller/PhabricatorNotificationListController.php', 'PhabricatorNotificationPanelController' => 'applications/notification/controller/PhabricatorNotificationPanelController.php', 'PhabricatorNotificationQuery' => 'applications/notification/PhabricatorNotificationQuery.php', 'PhabricatorNotificationStatusController' => 'applications/notification/controller/PhabricatorNotificationStatusController.php', 'PhabricatorOAuthClientAuthorization' => 'applications/oauthserver/storage/PhabricatorOAuthClientAuthorization.php', 'PhabricatorOAuthClientAuthorizationBaseController' => 'applications/oauthserver/controller/clientauthorization/PhabricatorOAuthClientAuthorizationBaseController.php', 'PhabricatorOAuthClientAuthorizationDeleteController' => 'applications/oauthserver/controller/clientauthorization/PhabricatorOAuthClientAuthorizationDeleteController.php', 'PhabricatorOAuthClientAuthorizationEditController' => 'applications/oauthserver/controller/clientauthorization/PhabricatorOAuthClientAuthorizationEditController.php', 'PhabricatorOAuthClientAuthorizationListController' => 'applications/oauthserver/controller/clientauthorization/PhabricatorOAuthClientAuthorizationListController.php', 'PhabricatorOAuthClientAuthorizationQuery' => 'applications/oauthserver/query/PhabricatorOAuthClientAuthorizationQuery.php', 'PhabricatorOAuthClientBaseController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientBaseController.php', 'PhabricatorOAuthClientDeleteController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientDeleteController.php', 'PhabricatorOAuthClientEditController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientEditController.php', 'PhabricatorOAuthClientListController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientListController.php', 'PhabricatorOAuthClientViewController' => 'applications/oauthserver/controller/client/PhabricatorOAuthClientViewController.php', 'PhabricatorOAuthDefaultRegistrationController' => 'applications/auth/controller/oauthregistration/PhabricatorOAuthDefaultRegistrationController.php', 'PhabricatorOAuthDiagnosticsController' => 'applications/auth/controller/PhabricatorOAuthDiagnosticsController.php', 'PhabricatorOAuthFailureView' => 'applications/auth/view/PhabricatorOAuthFailureView.php', 'PhabricatorOAuthLoginController' => 'applications/auth/controller/PhabricatorOAuthLoginController.php', 'PhabricatorOAuthProvider' => 'applications/auth/oauth/provider/PhabricatorOAuthProvider.php', 'PhabricatorOAuthProviderDisqus' => 'applications/auth/oauth/provider/PhabricatorOAuthProviderDisqus.php', 'PhabricatorOAuthProviderException' => 'applications/auth/oauth/provider/PhabricatorOAuthProviderException.php', 'PhabricatorOAuthProviderFacebook' => 'applications/auth/oauth/provider/PhabricatorOAuthProviderFacebook.php', 'PhabricatorOAuthProviderGitHub' => 'applications/auth/oauth/provider/PhabricatorOAuthProviderGitHub.php', 'PhabricatorOAuthProviderGoogle' => 'applications/auth/oauth/provider/PhabricatorOAuthProviderGoogle.php', 'PhabricatorOAuthProviderPhabricator' => 'applications/auth/oauth/provider/PhabricatorOAuthProviderPhabricator.php', 'PhabricatorOAuthRegistrationController' => 'applications/auth/controller/oauthregistration/PhabricatorOAuthRegistrationController.php', 'PhabricatorOAuthResponse' => 'applications/oauthserver/PhabricatorOAuthResponse.php', 'PhabricatorOAuthServer' => 'applications/oauthserver/PhabricatorOAuthServer.php', 'PhabricatorOAuthServerAccessToken' => 'applications/oauthserver/storage/PhabricatorOAuthServerAccessToken.php', 'PhabricatorOAuthServerAuthController' => 'applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php', 'PhabricatorOAuthServerAuthorizationCode' => 'applications/oauthserver/storage/PhabricatorOAuthServerAuthorizationCode.php', 'PhabricatorOAuthServerClient' => 'applications/oauthserver/storage/PhabricatorOAuthServerClient.php', 'PhabricatorOAuthServerClientQuery' => 'applications/oauthserver/query/PhabricatorOAuthServerClientQuery.php', 'PhabricatorOAuthServerController' => 'applications/oauthserver/controller/PhabricatorOAuthServerController.php', 'PhabricatorOAuthServerDAO' => 'applications/oauthserver/storage/PhabricatorOAuthServerDAO.php', 'PhabricatorOAuthServerScope' => 'applications/oauthserver/PhabricatorOAuthServerScope.php', 'PhabricatorOAuthServerTestCase' => 'applications/oauthserver/__tests__/PhabricatorOAuthServerTestCase.php', 'PhabricatorOAuthServerTestController' => 'applications/oauthserver/controller/PhabricatorOAuthServerTestController.php', 'PhabricatorOAuthServerTokenController' => 'applications/oauthserver/controller/PhabricatorOAuthServerTokenController.php', 'PhabricatorOAuthUnlinkController' => 'applications/auth/controller/PhabricatorOAuthUnlinkController.php', 'PhabricatorObjectHandle' => 'applications/phid/PhabricatorObjectHandle.php', 'PhabricatorObjectHandleConstants' => 'applications/phid/handle/const/PhabricatorObjectHandleConstants.php', 'PhabricatorObjectHandleData' => 'applications/phid/handle/PhabricatorObjectHandleData.php', 'PhabricatorObjectHandleStatus' => 'applications/phid/handle/const/PhabricatorObjectHandleStatus.php', 'PhabricatorObjectItemListView' => 'view/layout/PhabricatorObjectItemListView.php', 'PhabricatorObjectItemView' => 'view/layout/PhabricatorObjectItemView.php', 'PhabricatorObjectListView' => 'view/control/PhabricatorObjectListView.php', 'PhabricatorObjectSelectorDialog' => 'view/control/PhabricatorObjectSelectorDialog.php', 'PhabricatorOffsetPagedQuery' => 'infrastructure/query/PhabricatorOffsetPagedQuery.php', 'PhabricatorOwnerPathQuery' => 'applications/owners/query/PhabricatorOwnerPathQuery.php', 'PhabricatorOwnersConfigOptions' => 'applications/owners/config/PhabricatorOwnersConfigOptions.php', 'PhabricatorOwnersController' => 'applications/owners/controller/PhabricatorOwnersController.php', 'PhabricatorOwnersDAO' => 'applications/owners/storage/PhabricatorOwnersDAO.php', 'PhabricatorOwnersDeleteController' => 'applications/owners/controller/PhabricatorOwnersDeleteController.php', 'PhabricatorOwnersDetailController' => 'applications/owners/controller/PhabricatorOwnersDetailController.php', 'PhabricatorOwnersEditController' => 'applications/owners/controller/PhabricatorOwnersEditController.php', 'PhabricatorOwnersListController' => 'applications/owners/controller/PhabricatorOwnersListController.php', 'PhabricatorOwnersOwner' => 'applications/owners/storage/PhabricatorOwnersOwner.php', 'PhabricatorOwnersPackage' => 'applications/owners/storage/PhabricatorOwnersPackage.php', 'PhabricatorOwnersPackagePathValidator' => 'applications/repository/worker/commitchangeparser/PhabricatorOwnersPackagePathValidator.php', 'PhabricatorOwnersPackageQuery' => 'applications/owners/query/PhabricatorOwnersPackageQuery.php', 'PhabricatorOwnersPackageTestCase' => 'applications/owners/storage/__tests__/PhabricatorOwnersPackageTestCase.php', 'PhabricatorOwnersPath' => 'applications/owners/storage/PhabricatorOwnersPath.php', 'PhabricatorPHDConfigOptions' => 'applications/config/option/PhabricatorPHDConfigOptions.php', 'PhabricatorPHID' => 'applications/phid/storage/PhabricatorPHID.php', 'PhabricatorPHIDConfigOptions' => 'applications/phid/config/PhabricatorPHIDConfigOptions.php', 'PhabricatorPHIDConstants' => 'applications/phid/PhabricatorPHIDConstants.php', 'PhabricatorPHIDController' => 'applications/phid/controller/PhabricatorPHIDController.php', 'PhabricatorPHIDLookupController' => 'applications/phid/controller/PhabricatorPHIDLookupController.php', 'PhabricatorPHPMailerConfigOptions' => 'applications/config/option/PhabricatorPHPMailerConfigOptions.php', 'PhabricatorPaste' => 'applications/paste/storage/PhabricatorPaste.php', 'PhabricatorPasteController' => 'applications/paste/controller/PhabricatorPasteController.php', 'PhabricatorPasteDAO' => 'applications/paste/storage/PhabricatorPasteDAO.php', 'PhabricatorPasteEditController' => 'applications/paste/controller/PhabricatorPasteEditController.php', 'PhabricatorPasteListController' => 'applications/paste/controller/PhabricatorPasteListController.php', 'PhabricatorPasteQuery' => 'applications/paste/query/PhabricatorPasteQuery.php', 'PhabricatorPasteViewController' => 'applications/paste/controller/PhabricatorPasteViewController.php', 'PhabricatorPeopleController' => 'applications/people/controller/PhabricatorPeopleController.php', 'PhabricatorPeopleEditController' => 'applications/people/controller/PhabricatorPeopleEditController.php', 'PhabricatorPeopleLdapController' => 'applications/people/controller/PhabricatorPeopleLdapController.php', 'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php', 'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php', 'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php', 'PhabricatorPeopleQuery' => 'applications/people/PhabricatorPeopleQuery.php', 'PhabricatorPhabricatorOAuthConfigOptions' => 'applications/config/option/PhabricatorPhabricatorOAuthConfigOptions.php', 'PhabricatorPhameConfigOptions' => 'applications/phame/config/PhabricatorPhameConfigOptions.php', 'PhabricatorPholioConfigOptions' => 'applications/pholio/config/PhabricatorPholioConfigOptions.php', 'PhabricatorPhrictionConfigOptions' => 'applications/phriction/config/PhabricatorPhrictionConfigOptions.php', 'PhabricatorPinboardItemView' => 'view/layout/PhabricatorPinboardItemView.php', 'PhabricatorPinboardView' => 'view/layout/PhabricatorPinboardView.php', 'PhabricatorPolicies' => 'applications/policy/constants/PhabricatorPolicies.php', 'PhabricatorPolicy' => 'applications/policy/filter/PhabricatorPolicy.php', 'PhabricatorPolicyAwareQuery' => 'infrastructure/query/policy/PhabricatorPolicyAwareQuery.php', 'PhabricatorPolicyAwareTestQuery' => 'applications/policy/__tests__/PhabricatorPolicyAwareTestQuery.php', 'PhabricatorPolicyCapability' => 'applications/policy/constants/PhabricatorPolicyCapability.php', 'PhabricatorPolicyConfigOptions' => 'applications/config/option/PhabricatorPolicyConfigOptions.php', 'PhabricatorPolicyConstants' => 'applications/policy/constants/PhabricatorPolicyConstants.php', 'PhabricatorPolicyException' => 'applications/policy/exception/PhabricatorPolicyException.php', 'PhabricatorPolicyFilter' => 'applications/policy/filter/PhabricatorPolicyFilter.php', 'PhabricatorPolicyInterface' => 'applications/policy/interface/PhabricatorPolicyInterface.php', 'PhabricatorPolicyQuery' => 'applications/policy/query/PhabricatorPolicyQuery.php', 'PhabricatorPolicyTestCase' => 'applications/policy/__tests__/PhabricatorPolicyTestCase.php', 'PhabricatorPolicyTestObject' => 'applications/policy/__tests__/PhabricatorPolicyTestObject.php', 'PhabricatorPolicyType' => 'applications/policy/constants/PhabricatorPolicyType.php', 'PhabricatorProfileHeaderView' => 'view/layout/PhabricatorProfileHeaderView.php', 'PhabricatorProject' => 'applications/project/storage/PhabricatorProject.php', 'PhabricatorProjectConstants' => 'applications/project/constants/PhabricatorProjectConstants.php', 'PhabricatorProjectController' => 'applications/project/controller/PhabricatorProjectController.php', 'PhabricatorProjectCreateController' => 'applications/project/controller/PhabricatorProjectCreateController.php', 'PhabricatorProjectDAO' => 'applications/project/storage/PhabricatorProjectDAO.php', 'PhabricatorProjectEditor' => 'applications/project/editor/PhabricatorProjectEditor.php', 'PhabricatorProjectEditorTestCase' => 'applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php', 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', 'PhabricatorProjectMembersEditController' => 'applications/project/controller/PhabricatorProjectMembersEditController.php', 'PhabricatorProjectNameCollisionException' => 'applications/project/exception/PhabricatorProjectNameCollisionException.php', 'PhabricatorProjectProfile' => 'applications/project/storage/PhabricatorProjectProfile.php', 'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php', 'PhabricatorProjectProfileEditController' => 'applications/project/controller/PhabricatorProjectProfileEditController.php', 'PhabricatorProjectQuery' => 'applications/project/query/PhabricatorProjectQuery.php', 'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php', 'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php', 'PhabricatorProjectTransactionType' => 'applications/project/constants/PhabricatorProjectTransactionType.php', 'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php', 'PhabricatorPropertyListExample' => 'applications/uiexample/examples/PhabricatorPropertyListExample.php', 'PhabricatorPropertyListView' => 'view/layout/PhabricatorPropertyListView.php', 'PhabricatorQuery' => 'infrastructure/query/PhabricatorQuery.php', 'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php', 'PhabricatorRedirectController' => 'applications/base/controller/PhabricatorRedirectController.php', 'PhabricatorRefreshCSRFController' => 'applications/auth/controller/PhabricatorRefreshCSRFController.php', 'PhabricatorRemarkupControl' => 'view/form/control/PhabricatorRemarkupControl.php', 'PhabricatorRemarkupRuleCountdown' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleCountdown.php', 'PhabricatorRemarkupRuleDifferential' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleDifferential.php', 'PhabricatorRemarkupRuleDifferentialHandle' => 'infrastructure/markup/rule/handle/PhabricatorRemarkupRuleDifferentialHandle.php', 'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleDiffusion.php', 'PhabricatorRemarkupRuleEmbedFile' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleEmbedFile.php', 'PhabricatorRemarkupRuleImageMacro' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleImageMacro.php', 'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleManiphest.php', 'PhabricatorRemarkupRuleManiphestHandle' => 'infrastructure/markup/rule/handle/PhabricatorRemarkupRuleManiphestHandle.php', 'PhabricatorRemarkupRuleMeme' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleMeme.php', 'PhabricatorRemarkupRuleMention' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleMention.php', 'PhabricatorRemarkupRuleObjectHandle' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleObjectHandle.php', 'PhabricatorRemarkupRuleObjectName' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleObjectName.php', 'PhabricatorRemarkupRulePaste' => 'infrastructure/markup/rule/PhabricatorRemarkupRulePaste.php', 'PhabricatorRemarkupRulePhriction' => 'infrastructure/markup/rule/PhabricatorRemarkupRulePhriction.php', 'PhabricatorRemarkupRuleYoutube' => 'infrastructure/markup/rule/PhabricatorRemarkupRuleYoutube.php', 'PhabricatorRepository' => 'applications/repository/storage/PhabricatorRepository.php', 'PhabricatorRepositoryArcanistProject' => 'applications/repository/storage/PhabricatorRepositoryArcanistProject.php', 'PhabricatorRepositoryArcanistProjectDeleteController' => 'applications/repository/controller/PhabricatorRepositoryArcanistProjectDeleteController.php', 'PhabricatorRepositoryArcanistProjectEditController' => 'applications/repository/controller/PhabricatorRepositoryArcanistProjectEditController.php', 'PhabricatorRepositoryAuditRequest' => 'applications/repository/storage/PhabricatorRepositoryAuditRequest.php', 'PhabricatorRepositoryBranch' => 'applications/repository/storage/PhabricatorRepositoryBranch.php', 'PhabricatorRepositoryCommit' => 'applications/repository/storage/PhabricatorRepositoryCommit.php', 'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php', 'PhabricatorRepositoryCommitData' => 'applications/repository/storage/PhabricatorRepositoryCommitData.php', 'PhabricatorRepositoryCommitHeraldWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitHeraldWorker.php', 'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php', 'PhabricatorRepositoryCommitOwnersWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php', 'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitParserWorker.php', 'PhabricatorRepositoryCommitSearchIndexer' => 'applications/repository/search/PhabricatorRepositoryCommitSearchIndexer.php', 'PhabricatorRepositoryConfigOptions' => 'applications/repository/PhabricatorRepositoryConfigOptions.php', 'PhabricatorRepositoryController' => 'applications/repository/controller/PhabricatorRepositoryController.php', 'PhabricatorRepositoryCreateController' => 'applications/repository/controller/PhabricatorRepositoryCreateController.php', 'PhabricatorRepositoryDAO' => 'applications/repository/storage/PhabricatorRepositoryDAO.php', 'PhabricatorRepositoryDeleteController' => 'applications/repository/controller/PhabricatorRepositoryDeleteController.php', 'PhabricatorRepositoryEditController' => 'applications/repository/controller/PhabricatorRepositoryEditController.php', 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryGitCommitChangeParserWorker.php', 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryGitCommitMessageParserWorker.php', 'PhabricatorRepositoryListController' => 'applications/repository/controller/PhabricatorRepositoryListController.php', 'PhabricatorRepositoryManagementDeleteWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDeleteWorkflow.php', 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementDiscoverWorkflow.php', 'PhabricatorRepositoryManagementListWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementListWorkflow.php', 'PhabricatorRepositoryManagementPullWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementPullWorkflow.php', 'PhabricatorRepositoryManagementWorkflow' => 'applications/repository/management/PhabricatorRepositoryManagementWorkflow.php', 'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryMercurialCommitChangeParserWorker.php', 'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryMercurialCommitMessageParserWorker.php', 'PhabricatorRepositoryPullLocalDaemon' => 'applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php', 'PhabricatorRepositoryPullLocalDaemonTestCase' => 'applications/repository/daemon/__tests__/PhabricatorRepositoryPullLocalDaemonTestCase.php', 'PhabricatorRepositoryQuery' => 'applications/repository/query/PhabricatorRepositoryQuery.php', 'PhabricatorRepositoryShortcut' => 'applications/repository/storage/PhabricatorRepositoryShortcut.php', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php', 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositorySvnCommitMessageParserWorker.php', 'PhabricatorRepositorySymbol' => 'applications/repository/storage/PhabricatorRepositorySymbol.php', 'PhabricatorRepositoryTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryTestCase.php', 'PhabricatorRepositoryType' => 'applications/repository/constants/PhabricatorRepositoryType.php', 'PhabricatorS3FileStorageEngine' => 'applications/files/engine/PhabricatorS3FileStorageEngine.php', 'PhabricatorSQLPatchList' => 'infrastructure/storage/patch/PhabricatorSQLPatchList.php', 'PhabricatorSSHWorkflow' => 'infrastructure/ssh/PhabricatorSSHWorkflow.php', 'PhabricatorScopedEnv' => 'infrastructure/env/PhabricatorScopedEnv.php', 'PhabricatorSearchAbstractDocument' => 'applications/search/index/PhabricatorSearchAbstractDocument.php', 'PhabricatorSearchAttachController' => 'applications/search/controller/PhabricatorSearchAttachController.php', 'PhabricatorSearchBaseController' => 'applications/search/controller/PhabricatorSearchBaseController.php', 'PhabricatorSearchConfigOptions' => 'applications/search/config/PhabricatorSearchConfigOptions.php', 'PhabricatorSearchController' => 'applications/search/controller/PhabricatorSearchController.php', 'PhabricatorSearchDAO' => 'applications/search/storage/PhabricatorSearchDAO.php', 'PhabricatorSearchDocument' => 'applications/search/storage/document/PhabricatorSearchDocument.php', 'PhabricatorSearchDocumentField' => 'applications/search/storage/document/PhabricatorSearchDocumentField.php', 'PhabricatorSearchDocumentIndexer' => 'applications/search/index/PhabricatorSearchDocumentIndexer.php', 'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/PhabricatorSearchDocumentRelationship.php', 'PhabricatorSearchEngine' => 'applications/search/engine/PhabricatorSearchEngine.php', 'PhabricatorSearchEngineElastic' => 'applications/search/engine/PhabricatorSearchEngineElastic.php', 'PhabricatorSearchEngineMySQL' => 'applications/search/engine/PhabricatorSearchEngineMySQL.php', 'PhabricatorSearchEngineSelector' => 'applications/search/selector/PhabricatorSearchEngineSelector.php', 'PhabricatorSearchField' => 'applications/search/constants/PhabricatorSearchField.php', 'PhabricatorSearchIndexer' => 'applications/search/index/PhabricatorSearchIndexer.php', 'PhabricatorSearchManagementIndexWorkflow' => 'applications/search/management/PhabricatorSearchManagementIndexWorkflow.php', 'PhabricatorSearchManagementWorkflow' => 'applications/search/management/PhabricatorSearchManagementWorkflow.php', 'PhabricatorSearchQuery' => 'applications/search/storage/PhabricatorSearchQuery.php', 'PhabricatorSearchRelationship' => 'applications/search/constants/PhabricatorSearchRelationship.php', 'PhabricatorSearchResultView' => 'applications/search/view/PhabricatorSearchResultView.php', 'PhabricatorSearchScope' => 'applications/search/constants/PhabricatorSearchScope.php', 'PhabricatorSearchSelectController' => 'applications/search/controller/PhabricatorSearchSelectController.php', 'PhabricatorSecurityConfigOptions' => 'applications/config/option/PhabricatorSecurityConfigOptions.php', 'PhabricatorSendGridConfigOptions' => 'applications/config/option/PhabricatorSendGridConfigOptions.php', 'PhabricatorSettingsAdjustController' => 'applications/settings/controller/PhabricatorSettingsAdjustController.php', 'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php', 'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php', 'PhabricatorSettingsPanelAccount' => 'applications/settings/panel/PhabricatorSettingsPanelAccount.php', 'PhabricatorSettingsPanelConduit' => 'applications/settings/panel/PhabricatorSettingsPanelConduit.php', 'PhabricatorSettingsPanelDisplayPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDisplayPreferences.php', 'PhabricatorSettingsPanelEmailAddresses' => 'applications/settings/panel/PhabricatorSettingsPanelEmailAddresses.php', 'PhabricatorSettingsPanelEmailPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelEmailPreferences.php', 'PhabricatorSettingsPanelHomePreferences' => 'applications/settings/panel/PhabricatorSettingsPanelHomePreferences.php', 'PhabricatorSettingsPanelLDAP' => 'applications/settings/panel/PhabricatorSettingsPanelLDAP.php', 'PhabricatorSettingsPanelOAuth' => 'applications/settings/panel/PhabricatorSettingsPanelOAuth.php', 'PhabricatorSettingsPanelPassword' => 'applications/settings/panel/PhabricatorSettingsPanelPassword.php', 'PhabricatorSettingsPanelProfile' => 'applications/settings/panel/PhabricatorSettingsPanelProfile.php', 'PhabricatorSettingsPanelSSHKeys' => 'applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php', 'PhabricatorSettingsPanelSearchPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelSearchPreferences.php', 'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php', 'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php', 'PhabricatorSetupCheckBaseURI' => 'applications/config/check/PhabricatorSetupCheckBaseURI.php', 'PhabricatorSetupCheckDatabase' => 'applications/config/check/PhabricatorSetupCheckDatabase.php', 'PhabricatorSetupCheckExtensions' => 'applications/config/check/PhabricatorSetupCheckExtensions.php', 'PhabricatorSetupCheckExtraConfig' => 'applications/config/check/PhabricatorSetupCheckExtraConfig.php', 'PhabricatorSetupCheckFacebook' => 'applications/config/check/PhabricatorSetupCheckFacebook.php', 'PhabricatorSetupCheckGD' => 'applications/config/check/PhabricatorSetupCheckGD.php', 'PhabricatorSetupCheckInvalidConfig' => 'applications/config/check/PhabricatorSetupCheckInvalidConfig.php', 'PhabricatorSetupCheckMail' => 'applications/config/check/PhabricatorSetupCheckMail.php', 'PhabricatorSetupCheckMySQL' => 'applications/config/check/PhabricatorSetupCheckMySQL.php', 'PhabricatorSetupCheckPHPConfig' => 'applications/config/check/PhabricatorSetupCheckPHPConfig.php', 'PhabricatorSetupCheckPath' => 'applications/config/check/PhabricatorSetupCheckPath.php', 'PhabricatorSetupCheckStorage' => 'applications/config/check/PhabricatorSetupCheckStorage.php', 'PhabricatorSetupCheckTimezone' => 'applications/config/check/PhabricatorSetupCheckTimezone.php', 'PhabricatorSetupIssue' => 'applications/config/issue/PhabricatorSetupIssue.php', 'PhabricatorSetupIssueExample' => 'applications/uiexample/examples/PhabricatorSetupIssueExample.php', 'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php', 'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/PhabricatorSlowvoteChoice.php', 'PhabricatorSlowvoteComment' => 'applications/slowvote/storage/PhabricatorSlowvoteComment.php', 'PhabricatorSlowvoteController' => 'applications/slowvote/controller/PhabricatorSlowvoteController.php', 'PhabricatorSlowvoteCreateController' => 'applications/slowvote/controller/PhabricatorSlowvoteCreateController.php', 'PhabricatorSlowvoteDAO' => 'applications/slowvote/storage/PhabricatorSlowvoteDAO.php', 'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/PhabricatorSlowvoteListController.php', 'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/PhabricatorSlowvoteOption.php', 'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/PhabricatorSlowvotePoll.php', 'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/PhabricatorSlowvotePollController.php', 'PhabricatorSlug' => 'infrastructure/util/PhabricatorSlug.php', 'PhabricatorSlugTestCase' => 'infrastructure/util/__tests__/PhabricatorSlugTestCase.php', 'PhabricatorSortTableExample' => 'applications/uiexample/examples/PhabricatorSortTableExample.php', 'PhabricatorSourceCodeView' => 'view/layout/PhabricatorSourceCodeView.php', 'PhabricatorStandardPageView' => 'view/page/PhabricatorStandardPageView.php', 'PhabricatorStatusController' => 'applications/status/PhabricatorStatusController.php', 'PhabricatorStorageFixtureScopeGuard' => 'infrastructure/testing/fixture/PhabricatorStorageFixtureScopeGuard.php', 'PhabricatorStorageManagementAPI' => 'infrastructure/storage/management/PhabricatorStorageManagementAPI.php', 'PhabricatorStorageManagementDatabasesWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDatabasesWorkflow.php', 'PhabricatorStorageManagementDestroyWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php', 'PhabricatorStorageManagementDumpWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php', 'PhabricatorStorageManagementStatusWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php', 'PhabricatorStorageManagementUpgradeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php', 'PhabricatorStorageManagementWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementWorkflow.php', 'PhabricatorStoragePatch' => 'infrastructure/storage/management/PhabricatorStoragePatch.php', 'PhabricatorSubscribableInterface' => 'applications/subscriptions/interface/PhabricatorSubscribableInterface.php', 'PhabricatorSubscribersQuery' => 'applications/subscriptions/query/PhabricatorSubscribersQuery.php', 'PhabricatorSubscriptionsEditController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php', 'PhabricatorSubscriptionsEditor' => 'applications/subscriptions/editor/PhabricatorSubscriptionsEditor.php', 'PhabricatorSubscriptionsUIEventListener' => 'applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php', 'PhabricatorSymbolNameLinter' => 'infrastructure/lint/hook/PhabricatorSymbolNameLinter.php', 'PhabricatorSyntaxHighlighter' => 'infrastructure/markup/PhabricatorSyntaxHighlighter.php', 'PhabricatorSyntaxHighlightingConfigOptions' => 'applications/config/option/PhabricatorSyntaxHighlightingConfigOptions.php', 'PhabricatorTagExample' => 'applications/uiexample/examples/PhabricatorTagExample.php', 'PhabricatorTagView' => 'view/layout/PhabricatorTagView.php', 'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/PhabricatorTaskmasterDaemon.php', 'PhabricatorTestCase' => 'infrastructure/testing/PhabricatorTestCase.php', 'PhabricatorTestWorker' => 'infrastructure/daemon/workers/__tests__/PhabricatorTestWorker.php', 'PhabricatorTimelineCursor' => 'infrastructure/daemon/timeline/storage/PhabricatorTimelineCursor.php', 'PhabricatorTimelineDAO' => 'infrastructure/daemon/timeline/storage/PhabricatorTimelineDAO.php', 'PhabricatorTimelineEvent' => 'infrastructure/daemon/timeline/storage/PhabricatorTimelineEvent.php', 'PhabricatorTimelineEventData' => 'infrastructure/daemon/timeline/storage/PhabricatorTimelineEventData.php', 'PhabricatorTimelineEventView' => 'view/layout/PhabricatorTimelineEventView.php', 'PhabricatorTimelineExample' => 'applications/uiexample/examples/PhabricatorTimelineExample.php', 'PhabricatorTimelineIterator' => 'infrastructure/daemon/timeline/cursor/PhabricatorTimelineIterator.php', 'PhabricatorTimelineView' => 'view/layout/PhabricatorTimelineView.php', 'PhabricatorTimer' => 'applications/countdown/storage/PhabricatorTimer.php', 'PhabricatorTransactionView' => 'view/layout/PhabricatorTransactionView.php', 'PhabricatorTransactions' => 'applications/transactions/constants/PhabricatorTransactions.php', 'PhabricatorTransformedFile' => 'applications/files/storage/PhabricatorTransformedFile.php', 'PhabricatorTranslation' => 'infrastructure/internationalization/PhabricatorTranslation.php', 'PhabricatorTranslationsConfigOptions' => 'applications/config/option/PhabricatorTranslationsConfigOptions.php', 'PhabricatorTrivialTestCase' => 'infrastructure/testing/__tests__/PhabricatorTrivialTestCase.php', 'PhabricatorTypeaheadCommonDatasourceController' => 'applications/typeahead/controller/PhabricatorTypeaheadCommonDatasourceController.php', 'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/PhabricatorTypeaheadDatasourceController.php', 'PhabricatorTypeaheadResult' => 'applications/typeahead/storage/PhabricatorTypeaheadResult.php', 'PhabricatorUIExample' => 'applications/uiexample/examples/PhabricatorUIExample.php', 'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/PhabricatorUIExampleRenderController.php', 'PhabricatorUIListFilterExample' => 'applications/uiexample/examples/PhabricatorUIListFilterExample.php', 'PhabricatorUINotificationExample' => 'applications/uiexample/examples/PhabricatorUINotificationExample.php', 'PhabricatorUIPagerExample' => 'applications/uiexample/examples/PhabricatorUIPagerExample.php', 'PhabricatorUITooltipExample' => 'applications/uiexample/examples/PhabricatorUITooltipExample.php', 'PhabricatorUnitsTestCase' => 'view/__tests__/PhabricatorUnitsTestCase.php', 'PhabricatorUser' => 'applications/people/storage/PhabricatorUser.php', 'PhabricatorUserDAO' => 'applications/people/storage/PhabricatorUserDAO.php', 'PhabricatorUserEditor' => 'applications/people/PhabricatorUserEditor.php', 'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php', 'PhabricatorUserLDAPInfo' => 'applications/people/storage/PhabricatorUserLDAPInfo.php', 'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php', 'PhabricatorUserOAuthInfo' => 'applications/people/storage/PhabricatorUserOAuthInfo.php', 'PhabricatorUserPreferences' => 'applications/settings/storage/PhabricatorUserPreferences.php', 'PhabricatorUserProfile' => 'applications/people/storage/PhabricatorUserProfile.php', 'PhabricatorUserSSHKey' => 'applications/settings/storage/PhabricatorUserSSHKey.php', 'PhabricatorUserSearchIndexer' => 'applications/people/search/PhabricatorUserSearchIndexer.php', 'PhabricatorUserStatus' => 'applications/people/storage/PhabricatorUserStatus.php', 'PhabricatorUserStatusInvalidEpochException' => 'applications/people/exception/PhabricatorUserStatusInvalidEpochException.php', 'PhabricatorUserStatusOverlapException' => 'applications/people/exception/PhabricatorUserStatusOverlapException.php', 'PhabricatorUserTestCase' => 'applications/people/storage/__tests__/PhabricatorUserTestCase.php', 'PhabricatorWorker' => 'infrastructure/daemon/workers/PhabricatorWorker.php', 'PhabricatorWorkerActiveTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerActiveTask.php', 'PhabricatorWorkerArchiveTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerArchiveTask.php', 'PhabricatorWorkerDAO' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerDAO.php', 'PhabricatorWorkerLeaseQuery' => 'infrastructure/daemon/workers/query/PhabricatorWorkerLeaseQuery.php', 'PhabricatorWorkerPermanentFailureException' => 'infrastructure/daemon/workers/exception/PhabricatorWorkerPermanentFailureException.php', 'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTask.php', 'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/PhabricatorWorkerTaskData.php', 'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/PhabricatorWorkerTaskDetailController.php', 'PhabricatorWorkerTaskUpdateController' => 'applications/daemon/controller/PhabricatorWorkerTaskUpdateController.php', 'PhabricatorWorkerTestCase' => 'infrastructure/daemon/workers/__tests__/PhabricatorWorkerTestCase.php', 'PhabricatorXHPASTViewController' => 'applications/phpast/controller/PhabricatorXHPASTViewController.php', 'PhabricatorXHPASTViewDAO' => 'applications/phpast/storage/PhabricatorXHPASTViewDAO.php', 'PhabricatorXHPASTViewFrameController' => 'applications/phpast/controller/PhabricatorXHPASTViewFrameController.php', 'PhabricatorXHPASTViewFramesetController' => 'applications/phpast/controller/PhabricatorXHPASTViewFramesetController.php', 'PhabricatorXHPASTViewInputController' => 'applications/phpast/controller/PhabricatorXHPASTViewInputController.php', 'PhabricatorXHPASTViewPanelController' => 'applications/phpast/controller/PhabricatorXHPASTViewPanelController.php', 'PhabricatorXHPASTViewParseTree' => 'applications/phpast/storage/PhabricatorXHPASTViewParseTree.php', 'PhabricatorXHPASTViewRunController' => 'applications/phpast/controller/PhabricatorXHPASTViewRunController.php', 'PhabricatorXHPASTViewStreamController' => 'applications/phpast/controller/PhabricatorXHPASTViewStreamController.php', 'PhabricatorXHPASTViewTreeController' => 'applications/phpast/controller/PhabricatorXHPASTViewTreeController.php', 'PhabricatorXHProfController' => 'applications/xhprof/controller/PhabricatorXHProfController.php', 'PhabricatorXHProfDAO' => 'applications/xhprof/storage/PhabricatorXHProfDAO.php', 'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/PhabricatorXHProfProfileController.php', 'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/PhabricatorXHProfProfileSymbolView.php', 'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/PhabricatorXHProfProfileTopLevelView.php', 'PhabricatorXHProfProfileView' => 'applications/xhprof/view/PhabricatorXHProfProfileView.php', 'PhabricatorXHProfSample' => 'applications/xhprof/storage/PhabricatorXHProfSample.php', 'PhabricatorXHProfSampleListController' => 'applications/xhprof/controller/PhabricatorXHProfSampleListController.php', 'PhabricatorXHProfSampleListView' => 'applications/xhprof/view/PhabricatorXHProfSampleListView.php', 'PhameBasicBlogSkin' => 'applications/phame/skins/PhameBasicBlogSkin.php', 'PhameBasicTemplateBlogSkin' => 'applications/phame/skins/PhameBasicTemplateBlogSkin.php', 'PhameBlog' => 'applications/phame/storage/PhameBlog.php', 'PhameBlogDeleteController' => 'applications/phame/controller/blog/PhameBlogDeleteController.php', 'PhameBlogEditController' => 'applications/phame/controller/blog/PhameBlogEditController.php', 'PhameBlogFeedController' => 'applications/phame/controller/blog/PhameBlogFeedController.php', 'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php', 'PhameBlogLiveController' => 'applications/phame/controller/blog/PhameBlogLiveController.php', 'PhameBlogQuery' => 'applications/phame/query/PhameBlogQuery.php', 'PhameBlogSkin' => 'applications/phame/skins/PhameBlogSkin.php', 'PhameBlogViewController' => 'applications/phame/controller/blog/PhameBlogViewController.php', 'PhameController' => 'applications/phame/controller/PhameController.php', 'PhameDAO' => 'applications/phame/storage/PhameDAO.php', 'PhamePost' => 'applications/phame/storage/PhamePost.php', 'PhamePostDeleteController' => 'applications/phame/controller/post/PhamePostDeleteController.php', 'PhamePostEditController' => 'applications/phame/controller/post/PhamePostEditController.php', 'PhamePostFramedController' => 'applications/phame/controller/post/PhamePostFramedController.php', 'PhamePostListController' => 'applications/phame/controller/post/PhamePostListController.php', 'PhamePostNewController' => 'applications/phame/controller/post/PhamePostNewController.php', 'PhamePostNotLiveController' => 'applications/phame/controller/post/PhamePostNotLiveController.php', 'PhamePostPreviewController' => 'applications/phame/controller/post/PhamePostPreviewController.php', 'PhamePostPublishController' => 'applications/phame/controller/post/PhamePostPublishController.php', 'PhamePostQuery' => 'applications/phame/query/PhamePostQuery.php', 'PhamePostUnpublishController' => 'applications/phame/controller/post/PhamePostUnpublishController.php', 'PhamePostView' => 'applications/phame/view/PhamePostView.php', 'PhamePostViewController' => 'applications/phame/controller/post/PhamePostViewController.php', 'PhameResourceController' => 'applications/phame/controller/PhameResourceController.php', 'PhameSkinSpecification' => 'applications/phame/skins/PhameSkinSpecification.php', 'PholioConstants' => 'applications/pholio/constants/PholioConstants.php', 'PholioController' => 'applications/pholio/controller/PholioController.php', 'PholioDAO' => 'applications/pholio/storage/PholioDAO.php', 'PholioImage' => 'applications/pholio/storage/PholioImage.php', 'PholioMock' => 'applications/pholio/storage/PholioMock.php', 'PholioMockCommentController' => 'applications/pholio/controller/PholioMockCommentController.php', 'PholioMockEditController' => 'applications/pholio/controller/PholioMockEditController.php', 'PholioMockEditor' => 'applications/pholio/editor/PholioMockEditor.php', 'PholioMockImagesView' => 'applications/pholio/view/PholioMockImagesView.php', 'PholioMockListController' => 'applications/pholio/controller/PholioMockListController.php', 'PholioMockQuery' => 'applications/pholio/query/PholioMockQuery.php', 'PholioMockViewController' => 'applications/pholio/controller/PholioMockViewController.php', 'PholioReplyHandler' => 'applications/pholio/mail/PholioReplyHandler.php', 'PholioSearchIndexer' => 'applications/pholio/search/PholioSearchIndexer.php', 'PholioTransaction' => 'applications/pholio/storage/PholioTransaction.php', 'PholioTransactionComment' => 'applications/pholio/storage/PholioTransactionComment.php', 'PholioTransactionQuery' => 'applications/pholio/query/PholioTransactionQuery.php', 'PholioTransactionType' => 'applications/pholio/constants/PholioTransactionType.php', 'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php', 'PhortuneStripeBaseController' => 'applications/phortune/stripe/controller/PhortuneStripeBaseController.php', 'PhortuneStripePaymentFormView' => 'applications/phortune/stripe/view/PhortuneStripePaymentFormView.php', 'PhortuneStripeTestPaymentFormController' => 'applications/phortune/stripe/controller/PhortuneStripeTestPaymentFormController.php', 'PhrictionActionConstants' => 'applications/phriction/constants/PhrictionActionConstants.php', 'PhrictionChangeType' => 'applications/phriction/constants/PhrictionChangeType.php', 'PhrictionConstants' => 'applications/phriction/constants/PhrictionConstants.php', 'PhrictionContent' => 'applications/phriction/storage/PhrictionContent.php', 'PhrictionController' => 'applications/phriction/controller/PhrictionController.php', 'PhrictionDAO' => 'applications/phriction/storage/PhrictionDAO.php', 'PhrictionDeleteController' => 'applications/phriction/controller/PhrictionDeleteController.php', 'PhrictionDiffController' => 'applications/phriction/controller/PhrictionDiffController.php', 'PhrictionDocument' => 'applications/phriction/storage/PhrictionDocument.php', 'PhrictionDocumentController' => 'applications/phriction/controller/PhrictionDocumentController.php', 'PhrictionDocumentEditor' => 'applications/phriction/editor/PhrictionDocumentEditor.php', 'PhrictionDocumentPreviewController' => 'applications/phriction/controller/PhrictionDocumentPreviewController.php', 'PhrictionDocumentStatus' => 'applications/phriction/constants/PhrictionDocumentStatus.php', 'PhrictionDocumentTestCase' => 'applications/phriction/storage/__tests__/PhrictionDocumentTestCase.php', 'PhrictionEditController' => 'applications/phriction/controller/PhrictionEditController.php', 'PhrictionHistoryController' => 'applications/phriction/controller/PhrictionHistoryController.php', 'PhrictionListController' => 'applications/phriction/controller/PhrictionListController.php', 'PhrictionNewController' => 'applications/phriction/controller/PhrictionNewController.php', 'PhrictionSearchIndexer' => 'applications/phriction/search/PhrictionSearchIndexer.php', 'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php', 'PonderAddCommentView' => 'applications/ponder/view/PonderAddCommentView.php', 'PonderAnswer' => 'applications/ponder/storage/PonderAnswer.php', 'PonderAnswerEditor' => 'applications/ponder/editor/PonderAnswerEditor.php', 'PonderAnswerListView' => 'applications/ponder/view/PonderAnswerListView.php', 'PonderAnswerPreviewController' => 'applications/ponder/controller/PonderAnswerPreviewController.php', 'PonderAnswerQuery' => 'applications/ponder/query/PonderAnswerQuery.php', 'PonderAnswerSaveController' => 'applications/ponder/controller/PonderAnswerSaveController.php', 'PonderAnswerViewController' => 'applications/ponder/controller/PonderAnswerViewController.php', 'PonderAnsweredMail' => 'applications/ponder/mail/PonderAnsweredMail.php', 'PonderComment' => 'applications/ponder/storage/PonderComment.php', 'PonderCommentEditor' => 'applications/ponder/editor/PonderCommentEditor.php', 'PonderCommentListView' => 'applications/ponder/view/PonderCommentListView.php', 'PonderCommentMail' => 'applications/ponder/mail/PonderCommentMail.php', 'PonderCommentQuery' => 'applications/ponder/query/PonderCommentQuery.php', 'PonderCommentSaveController' => 'applications/ponder/controller/PonderCommentSaveController.php', 'PonderConstants' => 'applications/ponder/PonderConstants.php', 'PonderController' => 'applications/ponder/controller/PonderController.php', 'PonderDAO' => 'applications/ponder/storage/PonderDAO.php', 'PonderFeedController' => 'applications/ponder/controller/PonderFeedController.php', 'PonderMail' => 'applications/ponder/mail/PonderMail.php', 'PonderMentionMail' => 'applications/ponder/mail/PonderMentionMail.php', 'PonderPostBodyView' => 'applications/ponder/view/PonderPostBodyView.php', 'PonderQuestion' => 'applications/ponder/storage/PonderQuestion.php', 'PonderQuestionAskController' => 'applications/ponder/controller/PonderQuestionAskController.php', 'PonderQuestionDetailView' => 'applications/ponder/view/PonderQuestionDetailView.php', 'PonderQuestionEditor' => 'applications/ponder/editor/PonderQuestionEditor.php', 'PonderQuestionPreviewController' => 'applications/ponder/controller/PonderQuestionPreviewController.php', 'PonderQuestionQuery' => 'applications/ponder/query/PonderQuestionQuery.php', 'PonderQuestionSummaryView' => 'applications/ponder/view/PonderQuestionSummaryView.php', 'PonderQuestionViewController' => 'applications/ponder/controller/PonderQuestionViewController.php', 'PonderReplyHandler' => 'applications/ponder/PonderReplyHandler.php', 'PonderRuleQuestion' => 'infrastructure/markup/rule/PonderRuleQuestion.php', 'PonderSearchIndexer' => 'applications/ponder/search/PonderSearchIndexer.php', 'PonderUserProfileView' => 'applications/ponder/view/PonderUserProfileView.php', 'PonderVotableInterface' => 'applications/ponder/storage/PonderVotableInterface.php', 'PonderVotableView' => 'applications/ponder/view/PonderVotableView.php', 'PonderVoteEditor' => 'applications/ponder/editor/PonderVoteEditor.php', 'PonderVoteSaveController' => 'applications/ponder/controller/PonderVoteSaveController.php', 'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php', ), 'function' => array( '_phabricator_date_format' => 'view/viewutils.php', 'celerity_generate_unique_node_id' => 'infrastructure/celerity/api.php', 'celerity_get_resource_uri' => 'infrastructure/celerity/api.php', 'celerity_register_resource_map' => 'infrastructure/celerity/map.php', 'javelin_render_tag' => 'infrastructure/javelin/markup.php', 'javelin_tag' => 'infrastructure/javelin/markup.php', 'phabricator_date' => 'view/viewutils.php', 'phabricator_datetime' => 'view/viewutils.php', 'phabricator_form' => 'infrastructure/javelin/markup.php', 'phabricator_format_bytes' => 'view/viewutils.php', 'phabricator_format_local_time' => 'view/viewutils.php', 'phabricator_format_relative_time' => 'view/viewutils.php', 'phabricator_format_relative_time_detailed' => 'view/viewutils.php', 'phabricator_format_units_generic' => 'view/viewutils.php', 'phabricator_on_relative_date' => 'view/viewutils.php', 'phabricator_parse_bytes' => 'view/viewutils.php', 'phabricator_relative_date' => 'view/viewutils.php', 'phabricator_render_form' => 'infrastructure/javelin/markup.php', 'phabricator_time' => 'view/viewutils.php', 'phid_get_subtype' => 'applications/phid/utils.php', 'phid_get_type' => 'applications/phid/utils.php', 'phid_group_by_type' => 'applications/phid/utils.php', 'require_celerity_resource' => 'infrastructure/celerity/api.php', ), 'xmap' => array( 'Aphront304Response' => 'AphrontResponse', 'Aphront400Response' => 'AphrontResponse', 'Aphront403Response' => 'AphrontHTMLResponse', 'Aphront404Response' => 'AphrontHTMLResponse', 'AphrontAjaxResponse' => 'AphrontResponse', 'AphrontAttachedFileView' => 'AphrontView', 'AphrontCSRFException' => 'AphrontException', 'AphrontCalendarEventView' => 'AphrontView', 'AphrontCalendarMonthView' => 'AphrontView', 'AphrontContextBarView' => 'AphrontView', 'AphrontController' => 'Phobject', 'AphrontCrumbsView' => 'AphrontView', 'AphrontCursorPagerView' => 'AphrontView', 'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration', 'AphrontDialogResponse' => 'AphrontResponse', 'AphrontDialogView' => 'AphrontView', 'AphrontErrorView' => 'AphrontView', 'AphrontException' => 'Exception', 'AphrontFileResponse' => 'AphrontResponse', 'AphrontFormCheckboxControl' => 'AphrontFormControl', 'AphrontFormControl' => 'AphrontView', 'AphrontFormDateControl' => 'AphrontFormControl', 'AphrontFormDividerControl' => 'AphrontFormControl', 'AphrontFormDragAndDropUploadControl' => 'AphrontFormControl', 'AphrontFormFileControl' => 'AphrontFormControl', 'AphrontFormImageControl' => 'AphrontFormControl', 'AphrontFormInsetView' => 'AphrontView', 'AphrontFormLayoutView' => 'AphrontView', 'AphrontFormMarkupControl' => 'AphrontFormControl', 'AphrontFormPasswordControl' => 'AphrontFormControl', 'AphrontFormPolicyControl' => 'AphrontFormControl', 'AphrontFormRadioButtonControl' => 'AphrontFormControl', 'AphrontFormRecaptchaControl' => 'AphrontFormControl', 'AphrontFormSelectControl' => 'AphrontFormControl', 'AphrontFormStaticControl' => 'AphrontFormControl', 'AphrontFormSubmitControl' => 'AphrontFormControl', 'AphrontFormTextAreaControl' => 'AphrontFormControl', 'AphrontFormTextControl' => 'AphrontFormControl', 'AphrontFormToggleButtonsControl' => 'AphrontFormControl', 'AphrontFormTokenizerControl' => 'AphrontFormControl', 'AphrontFormView' => 'AphrontView', 'AphrontHTMLResponse' => 'AphrontResponse', 'AphrontHTTPSinkTestCase' => 'PhabricatorTestCase', 'AphrontIsolatedDatabaseConnectionTestCase' => 'PhabricatorTestCase', 'AphrontIsolatedHTTPSink' => 'AphrontHTTPSink', 'AphrontJSONResponse' => 'AphrontResponse', 'AphrontJavelinView' => 'AphrontView', 'AphrontKeyboardShortcutsAvailableView' => 'AphrontView', 'AphrontListFilterView' => 'AphrontView', 'AphrontMiniPanelView' => 'AphrontView', 'AphrontMoreView' => 'AphrontView', 'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase', 'AphrontNullView' => 'AphrontView', 'AphrontPHPHTTPSink' => 'AphrontHTTPSink', 'AphrontPageView' => 'AphrontView', 'AphrontPagerView' => 'AphrontView', 'AphrontPanelView' => 'AphrontView', 'AphrontPlainTextResponse' => 'AphrontResponse', 'AphrontProxyResponse' => 'AphrontResponse', 'AphrontRedirectException' => 'AphrontException', 'AphrontRedirectResponse' => 'AphrontResponse', 'AphrontReloadResponse' => 'AphrontRedirectResponse', 'AphrontRequestFailureView' => 'AphrontView', 'AphrontRequestTestCase' => 'PhabricatorTestCase', 'AphrontSideNavFilterView' => 'AphrontView', 'AphrontTableView' => 'AphrontView', 'AphrontTagView' => 'AphrontView', 'AphrontTokenizerTemplateView' => 'AphrontView', 'AphrontTypeaheadTemplateView' => 'AphrontView', 'AphrontUsageException' => 'AphrontException', 'AphrontView' => 'Phobject', 'AphrontWebpageResponse' => 'AphrontHTMLResponse', 'CelerityPhabricatorResourceController' => 'CelerityResourceController', 'CelerityResourceController' => 'PhabricatorController', 'CelerityResourceGraph' => 'AbstractDirectedGraph', 'CelerityResourceTransformerTestCase' => 'PhabricatorTestCase', 'ConduitAPI_arcanist_Method' => 'ConduitAPIMethod', 'ConduitAPI_arcanist_projectinfo_Method' => 'ConduitAPI_arcanist_Method', 'ConduitAPI_audit_Method' => 'ConduitAPIMethod', 'ConduitAPI_audit_query_Method' => 'ConduitAPI_audit_Method', 'ConduitAPI_chatlog_Method' => 'ConduitAPIMethod', 'ConduitAPI_chatlog_query_Method' => 'ConduitAPI_chatlog_Method', 'ConduitAPI_chatlog_record_Method' => 'ConduitAPI_chatlog_Method', 'ConduitAPI_conduit_connect_Method' => 'ConduitAPIMethod', 'ConduitAPI_conduit_getcertificate_Method' => 'ConduitAPIMethod', 'ConduitAPI_conduit_ping_Method' => 'ConduitAPIMethod', 'ConduitAPI_conduit_query_Method' => 'ConduitAPIMethod', 'ConduitAPI_daemon_launched_Method' => 'ConduitAPIMethod', 'ConduitAPI_daemon_log_Method' => 'ConduitAPIMethod', 'ConduitAPI_daemon_setstatus_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_close_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_createcomment_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_creatediff_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_createinline_Method' => 'ConduitAPI_differential_Method', 'ConduitAPI_differential_createrawdiff_Method' => 'ConduitAPI_differential_Method', 'ConduitAPI_differential_createrevision_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_find_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_finishpostponedlinters_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_getrevisioncomments_Method' => 'ConduitAPI_differential_Method', 'ConduitAPI_differential_getrevisionfeedback_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_markcommitted_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_parsecommitmessage_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_query_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_updaterevision_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_updateunitresults_Method' => 'ConduitAPIMethod', 'ConduitAPI_diffusion_findsymbols_Method' => 'ConduitAPIMethod', 'ConduitAPI_diffusion_getcommits_Method' => 'ConduitAPIMethod', 'ConduitAPI_diffusion_getlintmessages_Method' => 'ConduitAPIMethod', 'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'ConduitAPIMethod', 'ConduitAPI_feed_publish_Method' => 'ConduitAPIMethod', 'ConduitAPI_feed_query_Method' => 'ConduitAPIMethod', 'ConduitAPI_file_download_Method' => 'ConduitAPIMethod', 'ConduitAPI_file_info_Method' => 'ConduitAPIMethod', 'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod', 'ConduitAPI_flag_Method' => 'ConduitAPIMethod', 'ConduitAPI_flag_delete_Method' => 'ConduitAPI_flag_Method', 'ConduitAPI_flag_edit_Method' => 'ConduitAPI_flag_Method', 'ConduitAPI_flag_query_Method' => 'ConduitAPI_flag_Method', 'ConduitAPI_macro_Method' => 'ConduitAPIMethod', 'ConduitAPI_macro_query_Method' => 'ConduitAPI_macro_Method', 'ConduitAPI_maniphest_Method' => 'ConduitAPIMethod', 'ConduitAPI_maniphest_createtask_Method' => 'ConduitAPI_maniphest_Method', 'ConduitAPI_maniphest_find_Method' => 'ConduitAPI_maniphest_query_Method', 'ConduitAPI_maniphest_gettasktransactions_Method' => 'ConduitAPI_maniphest_Method', 'ConduitAPI_maniphest_info_Method' => 'ConduitAPI_maniphest_Method', 'ConduitAPI_maniphest_query_Method' => 'ConduitAPI_maniphest_Method', 'ConduitAPI_maniphest_update_Method' => 'ConduitAPI_maniphest_Method', 'ConduitAPI_owners_query_Method' => 'ConduitAPIMethod', 'ConduitAPI_paste_Method' => 'ConduitAPIMethod', 'ConduitAPI_paste_create_Method' => 'ConduitAPI_paste_Method', 'ConduitAPI_paste_info_Method' => 'ConduitAPI_paste_Method', 'ConduitAPI_paste_query_Method' => 'ConduitAPI_paste_Method', 'ConduitAPI_phid_Method' => 'ConduitAPIMethod', 'ConduitAPI_phid_info_Method' => 'ConduitAPI_phid_Method', 'ConduitAPI_phid_lookup_Method' => 'ConduitAPI_phid_Method', 'ConduitAPI_phid_query_Method' => 'ConduitAPI_phid_Method', 'ConduitAPI_phpast_getast_Method' => 'ConduitAPIMethod', 'ConduitAPI_phpast_version_Method' => 'ConduitAPIMethod', 'ConduitAPI_phriction_Method' => 'ConduitAPIMethod', 'ConduitAPI_phriction_edit_Method' => 'ConduitAPI_phriction_Method', 'ConduitAPI_phriction_history_Method' => 'ConduitAPI_phriction_Method', 'ConduitAPI_phriction_info_Method' => 'ConduitAPI_phriction_Method', 'ConduitAPI_project_Method' => 'ConduitAPIMethod', 'ConduitAPI_project_query_Method' => 'ConduitAPI_project_Method', 'ConduitAPI_remarkup_process_Method' => 'ConduitAPIMethod', 'ConduitAPI_repository_Method' => 'ConduitAPIMethod', 'ConduitAPI_repository_create_Method' => 'ConduitAPI_repository_Method', 'ConduitAPI_repository_query_Method' => 'ConduitAPI_repository_Method', 'ConduitAPI_slowvote_info_Method' => 'ConduitAPIMethod', 'ConduitAPI_user_Method' => 'ConduitAPIMethod', 'ConduitAPI_user_addstatus_Method' => 'ConduitAPI_user_Method', 'ConduitAPI_user_disable_Method' => 'ConduitAPI_user_Method', 'ConduitAPI_user_enable_Method' => 'ConduitAPI_user_Method', 'ConduitAPI_user_find_Method' => 'ConduitAPI_user_Method', 'ConduitAPI_user_info_Method' => 'ConduitAPI_user_Method', 'ConduitAPI_user_query_Method' => 'ConduitAPI_user_Method', 'ConduitAPI_user_removestatus_Method' => 'ConduitAPI_user_Method', 'ConduitAPI_user_whoami_Method' => 'ConduitAPI_user_Method', 'ConduitCallTestCase' => 'PhabricatorTestCase', 'ConduitException' => 'Exception', 'ConduitSSHWorkflow' => 'PhabricatorSSHWorkflow', 'ConpherenceConfigOptions' => 'PhabricatorApplicationConfigOptions', 'ConpherenceController' => 'PhabricatorController', 'ConpherenceDAO' => 'PhabricatorLiskDAO', 'ConpherenceEditor' => 'PhabricatorApplicationTransactionEditor', 'ConpherenceListController' => 'ConpherenceController', 'ConpherenceMenuItemView' => 'AphrontTagView', 'ConpherenceNewController' => 'ConpherenceController', 'ConpherenceParticipant' => 'ConpherenceDAO', 'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery', 'ConpherenceParticipationStatus' => 'ConpherenceConstants', 'ConpherenceReplyHandler' => 'PhabricatorMailReplyHandler', 'ConpherenceThread' => array( 0 => 'ConpherenceDAO', 1 => 'PhabricatorPolicyInterface', ), 'ConpherenceThreadQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ConpherenceTransaction' => 'PhabricatorApplicationTransaction', 'ConpherenceTransactionComment' => 'PhabricatorApplicationTransactionComment', 'ConpherenceTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'ConpherenceTransactionType' => 'ConpherenceConstants', 'ConpherenceTransactionView' => 'AphrontView', 'ConpherenceUpdateController' => 'ConpherenceController', 'ConpherenceViewController' => 'ConpherenceController', 'DarkConsoleController' => 'PhabricatorController', 'DarkConsoleDataController' => 'PhabricatorController', 'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin', 'DarkConsoleEventPlugin' => 'DarkConsolePlugin', 'DarkConsoleEventPluginAPI' => 'PhutilEventListener', 'DarkConsoleRequestPlugin' => 'DarkConsolePlugin', 'DarkConsoleServicesPlugin' => 'DarkConsolePlugin', 'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin', 'DefaultDatabaseConfigurationProvider' => 'DatabaseConfigurationProvider', 'DifferentialActionHasNoEffectException' => 'DifferentialException', 'DifferentialAddCommentView' => 'AphrontView', 'DifferentialAffectedPath' => 'DifferentialDAO', 'DifferentialApplyPatchFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialArcanistProjectFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialAuditorsFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialAuthorFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialAuxiliaryField' => 'DifferentialDAO', 'DifferentialBlameRevisionFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialBranchFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialCCWelcomeMail' => 'DifferentialReviewRequestMail', 'DifferentialCCsFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialChangeset' => 'DifferentialDAO', 'DifferentialChangesetDetailView' => 'AphrontView', 'DifferentialChangesetHTMLRenderer' => 'DifferentialChangesetRenderer', 'DifferentialChangesetListView' => 'AphrontView', 'DifferentialChangesetOneUpRenderer' => 'DifferentialChangesetHTMLRenderer', 'DifferentialChangesetOneUpTestRenderer' => 'DifferentialChangesetTestRenderer', 'DifferentialChangesetParserTestCase' => 'PhabricatorTestCase', 'DifferentialChangesetTestRenderer' => 'DifferentialChangesetRenderer', 'DifferentialChangesetTwoUpRenderer' => 'DifferentialChangesetHTMLRenderer', 'DifferentialChangesetTwoUpTestRenderer' => 'DifferentialChangesetTestRenderer', 'DifferentialChangesetViewController' => 'DifferentialController', 'DifferentialComment' => array( 0 => 'DifferentialDAO', 1 => 'PhabricatorMarkupInterface', ), 'DifferentialCommentEditor' => 'PhabricatorEditor', 'DifferentialCommentMail' => 'DifferentialMail', 'DifferentialCommentPreviewController' => 'DifferentialController', 'DifferentialCommentSaveController' => 'DifferentialController', 'DifferentialCommitsFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialConflictsFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialController' => 'PhabricatorController', 'DifferentialDAO' => 'PhabricatorLiskDAO', 'DifferentialDateCreatedFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialDateModifiedFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialDefaultFieldSelector' => 'DifferentialFieldSelector', 'DifferentialDependenciesFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialDependsOnFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialDiff' => 'DifferentialDAO', 'DifferentialDiffContentMail' => 'DifferentialMail', 'DifferentialDiffCreateController' => 'DifferentialController', 'DifferentialDiffProperty' => 'DifferentialDAO', 'DifferentialDiffTableOfContentsView' => 'AphrontView', 'DifferentialDiffTestCase' => 'ArcanistPhutilTestCase', 'DifferentialDiffViewController' => 'DifferentialController', 'DifferentialException' => 'Exception', 'DifferentialExceptionMail' => 'DifferentialMail', 'DifferentialExportPatchFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialFieldDataNotAvailableException' => 'Exception', 'DifferentialFieldParseException' => 'Exception', 'DifferentialFieldSpecificationIncompleteException' => 'Exception', 'DifferentialFieldValidationException' => 'Exception', 'DifferentialFreeformFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialGitSVNIDFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialHostFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialHunk' => 'DifferentialDAO', 'DifferentialHunkParserTestCase' => 'PhabricatorTestCase', 'DifferentialHunkTestCase' => 'ArcanistPhutilTestCase', 'DifferentialInlineComment' => array( 0 => 'DifferentialDAO', 1 => 'PhabricatorInlineCommentInterface', ), 'DifferentialInlineCommentEditController' => 'PhabricatorInlineCommentController', 'DifferentialInlineCommentEditView' => 'AphrontView', 'DifferentialInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController', 'DifferentialInlineCommentView' => 'AphrontView', 'DifferentialLinesFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialLintFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialLocalCommitsView' => 'AphrontView', 'DifferentialManiphestTasksFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail', 'DifferentialParseRenderTestCase' => 'PhabricatorTestCase', 'DifferentialPathFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialPrimaryPaneView' => 'AphrontView', 'DifferentialReplyHandler' => 'PhabricatorMailReplyHandler', 'DifferentialResultsTableView' => 'AphrontView', 'DifferentialRevertPlanFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialReviewRequestMail' => 'DifferentialMail', 'DifferentialReviewedByFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialReviewerStatsTestCase' => 'PhabricatorTestCase', 'DifferentialReviewersFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialRevision' => 'DifferentialDAO', 'DifferentialRevisionCommentListView' => 'AphrontView', 'DifferentialRevisionCommentView' => 'AphrontView', 'DifferentialRevisionDetailView' => 'AphrontView', 'DifferentialRevisionEditController' => 'DifferentialController', 'DifferentialRevisionEditor' => 'PhabricatorEditor', 'DifferentialRevisionIDFieldParserTestCase' => 'PhabricatorTestCase', 'DifferentialRevisionIDFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialRevisionListController' => 'DifferentialController', 'DifferentialRevisionListView' => 'AphrontView', 'DifferentialRevisionStatsController' => 'DifferentialController', 'DifferentialRevisionStatsView' => 'AphrontView', 'DifferentialRevisionStatusFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialRevisionUpdateHistoryView' => 'AphrontView', 'DifferentialRevisionViewController' => 'DifferentialController', 'DifferentialSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'DifferentialSubscribeController' => 'DifferentialController', 'DifferentialSummaryFieldSpecification' => 'DifferentialFreeformFieldSpecification', 'DifferentialTestPlanFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialTitleFieldSpecification' => 'DifferentialFreeformFieldSpecification', 'DifferentialUnitFieldSpecification' => 'DifferentialFieldSpecification', 'DiffusionBranchTableController' => 'DiffusionController', 'DiffusionBranchTableView' => 'DiffusionView', 'DiffusionBrowseController' => 'DiffusionController', 'DiffusionBrowseFileController' => 'DiffusionController', 'DiffusionBrowseTableView' => 'DiffusionView', 'DiffusionChangeController' => 'DiffusionController', 'DiffusionCommentListView' => 'AphrontView', 'DiffusionCommentView' => 'AphrontView', 'DiffusionCommitBranchesController' => 'DiffusionController', 'DiffusionCommitChangeTableView' => 'DiffusionView', 'DiffusionCommitController' => 'DiffusionController', 'DiffusionCommitEditController' => 'DiffusionController', 'DiffusionCommitParentsQuery' => 'DiffusionQuery', 'DiffusionCommitTagsController' => 'DiffusionController', 'DiffusionCommitTagsQuery' => 'DiffusionQuery', 'DiffusionContainsQuery' => 'DiffusionQuery', 'DiffusionController' => 'PhabricatorController', 'DiffusionDiffController' => 'DiffusionController', 'DiffusionDiffQuery' => 'DiffusionQuery', 'DiffusionEmptyResultView' => 'DiffusionView', 'DiffusionExistsQuery' => 'DiffusionQuery', 'DiffusionExternalController' => 'DiffusionController', 'DiffusionFileContentQuery' => 'DiffusionQuery', 'DiffusionGitBranchQuery' => 'DiffusionBranchQuery', 'DiffusionGitBranchQueryTestCase' => 'PhabricatorTestCase', 'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery', 'DiffusionGitCommitParentsQuery' => 'DiffusionCommitParentsQuery', 'DiffusionGitCommitTagsQuery' => 'DiffusionCommitTagsQuery', 'DiffusionGitContainsQuery' => 'DiffusionContainsQuery', 'DiffusionGitDiffQuery' => 'DiffusionDiffQuery', 'DiffusionGitExistsQuery' => 'DiffusionExistsQuery', 'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionGitHistoryQuery' => 'DiffusionHistoryQuery', 'DiffusionGitLastModifiedQuery' => 'DiffusionLastModifiedQuery', 'DiffusionGitMergedCommitsQuery' => 'DiffusionMergedCommitsQuery', 'DiffusionGitRawDiffQuery' => 'DiffusionRawDiffQuery', 'DiffusionGitRequest' => 'DiffusionRequest', 'DiffusionGitTagListQuery' => 'DiffusionTagListQuery', 'DiffusionHistoryController' => 'DiffusionController', 'DiffusionHistoryQuery' => 'DiffusionQuery', 'DiffusionHistoryTableView' => 'DiffusionView', 'DiffusionHomeController' => 'DiffusionController', 'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController', 'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController', 'DiffusionLastModifiedController' => 'DiffusionController', 'DiffusionLastModifiedQuery' => 'DiffusionQuery', 'DiffusionLintController' => 'DiffusionController', 'DiffusionLintDetailsController' => 'DiffusionController', 'DiffusionMercurialBranchQuery' => 'DiffusionBranchQuery', 'DiffusionMercurialBrowseQuery' => 'DiffusionBrowseQuery', 'DiffusionMercurialCommitParentsQuery' => 'DiffusionCommitParentsQuery', 'DiffusionMercurialCommitTagsQuery' => 'DiffusionCommitTagsQuery', 'DiffusionMercurialContainsQuery' => 'DiffusionContainsQuery', 'DiffusionMercurialDiffQuery' => 'DiffusionDiffQuery', 'DiffusionMercurialExistsQuery' => 'DiffusionExistsQuery', 'DiffusionMercurialFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionMercurialHistoryQuery' => 'DiffusionHistoryQuery', 'DiffusionMercurialLastModifiedQuery' => 'DiffusionLastModifiedQuery', 'DiffusionMercurialMergedCommitsQuery' => 'DiffusionMergedCommitsQuery', 'DiffusionMercurialRawDiffQuery' => 'DiffusionRawDiffQuery', 'DiffusionMercurialRequest' => 'DiffusionRequest', 'DiffusionMercurialTagListQuery' => 'DiffusionTagListQuery', 'DiffusionMergedCommitsQuery' => 'DiffusionQuery', 'DiffusionPathCompleteController' => 'DiffusionController', 'DiffusionPathQueryTestCase' => 'PhabricatorTestCase', 'DiffusionPathValidateController' => 'DiffusionController', 'DiffusionRawDiffQuery' => 'DiffusionQuery', 'DiffusionRepositoryController' => 'DiffusionController', 'DiffusionSetupException' => 'AphrontUsageException', 'DiffusionSvnBrowseQuery' => 'DiffusionBrowseQuery', 'DiffusionSvnCommitParentsQuery' => 'DiffusionCommitParentsQuery', 'DiffusionSvnCommitTagsQuery' => 'DiffusionCommitTagsQuery', 'DiffusionSvnContainsQuery' => 'DiffusionContainsQuery', 'DiffusionSvnDiffQuery' => 'DiffusionDiffQuery', 'DiffusionSvnExistsQuery' => 'DiffusionExistsQuery', 'DiffusionSvnFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionSvnHistoryQuery' => 'DiffusionHistoryQuery', 'DiffusionSvnLastModifiedQuery' => 'DiffusionLastModifiedQuery', 'DiffusionSvnMergedCommitsQuery' => 'DiffusionMergedCommitsQuery', 'DiffusionSvnRawDiffQuery' => 'DiffusionRawDiffQuery', 'DiffusionSvnRequest' => 'DiffusionRequest', 'DiffusionSvnTagListQuery' => 'DiffusionTagListQuery', 'DiffusionSymbolController' => 'DiffusionController', 'DiffusionSymbolQuery' => 'PhabricatorOffsetPagedQuery', 'DiffusionTagListController' => 'DiffusionController', 'DiffusionTagListQuery' => 'DiffusionQuery', 'DiffusionTagListView' => 'DiffusionView', 'DiffusionURITestCase' => 'ArcanistPhutilTestCase', 'DiffusionView' => 'AphrontView', 'DivinerArticleAtomizer' => 'DivinerAtomizer', 'DivinerAtomizeWorkflow' => 'DivinerWorkflow', 'DivinerFileAtomizer' => 'DivinerAtomizer', 'DivinerGenerateWorkflow' => 'DivinerWorkflow', 'DivinerListController' => 'PhabricatorController', 'DivinerWorkflow' => 'PhutilArgumentWorkflow', 'DrydockAllocatorWorker' => 'PhabricatorWorker', 'DrydockApacheWebrootInterface' => 'DrydockWebrootInterface', 'DrydockCommandInterface' => 'DrydockInterface', 'DrydockController' => 'PhabricatorController', 'DrydockDAO' => 'PhabricatorLiskDAO', 'DrydockLease' => 'DrydockDAO', 'DrydockLeaseListController' => 'DrydockController', 'DrydockLeaseQuery' => 'PhabricatorOffsetPagedQuery', 'DrydockLeaseReleaseController' => 'DrydockController', 'DrydockLeaseStatus' => 'DrydockConstants', 'DrydockLeaseViewController' => 'DrydockController', 'DrydockLocalCommandInterface' => 'DrydockCommandInterface', 'DrydockLocalHostBlueprint' => 'DrydockBlueprint', 'DrydockLog' => 'DrydockDAO', 'DrydockLogController' => 'DrydockController', 'DrydockLogQuery' => 'PhabricatorOffsetPagedQuery', 'DrydockManagementCloseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementLeaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementReleaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementWaitForLeaseWorkflow' => 'DrydockManagementWorkflow', 'DrydockManagementWorkflow' => 'PhutilArgumentWorkflow', 'DrydockResource' => 'DrydockDAO', 'DrydockResourceCloseController' => 'DrydockController', 'DrydockResourceListController' => 'DrydockController', 'DrydockResourceQuery' => 'PhabricatorOffsetPagedQuery', 'DrydockResourceStatus' => 'DrydockConstants', 'DrydockResourceViewController' => 'DrydockController', 'DrydockSSHCommandInterface' => 'DrydockCommandInterface', 'DrydockWebrootInterface' => 'DrydockInterface', 'DrydockWorkingCopyBlueprint' => 'DrydockBlueprint', 'FeedPublisherWorker' => 'PhabricatorWorker', 'HarbormasterDAO' => 'PhabricatorLiskDAO', 'HarbormasterObject' => 'HarbormasterDAO', 'HarbormasterRunnerWorker' => 'PhabricatorWorker', 'HarbormasterScratchTable' => 'HarbormasterDAO', 'HeraldAction' => 'HeraldDAO', 'HeraldApplyTranscript' => 'HeraldDAO', 'HeraldCommitAdapter' => 'HeraldObjectAdapter', 'HeraldCondition' => 'HeraldDAO', 'HeraldController' => 'PhabricatorController', 'HeraldDAO' => 'PhabricatorLiskDAO', 'HeraldDeleteController' => 'HeraldController', 'HeraldDifferentialRevisionAdapter' => 'HeraldObjectAdapter', 'HeraldDryRunAdapter' => 'HeraldObjectAdapter', 'HeraldEditLogQuery' => 'PhabricatorOffsetPagedQuery', 'HeraldHomeController' => 'HeraldController', 'HeraldInvalidConditionException' => 'Exception', 'HeraldInvalidFieldException' => 'Exception', 'HeraldNewController' => 'HeraldController', 'HeraldRecursiveConditionsException' => 'Exception', 'HeraldRule' => 'HeraldDAO', 'HeraldRuleController' => 'HeraldController', 'HeraldRuleEdit' => 'HeraldDAO', 'HeraldRuleEditHistoryController' => 'HeraldController', 'HeraldRuleEditHistoryView' => 'AphrontView', 'HeraldRuleListView' => 'AphrontView', 'HeraldRuleQuery' => 'PhabricatorOffsetPagedQuery', 'HeraldTestConsoleController' => 'HeraldController', 'HeraldTranscript' => 'HeraldDAO', 'HeraldTranscriptController' => 'HeraldController', 'HeraldTranscriptListController' => 'HeraldController', 'JavelinReactorExample' => 'PhabricatorUIExample', 'JavelinUIExample' => 'PhabricatorUIExample', 'JavelinViewExample' => 'PhabricatorUIExample', 'JavelinViewExampleServerView' => 'AphrontView', 'LiskChunkTestCase' => 'PhabricatorTestCase', 'LiskDAOTestCase' => 'PhabricatorTestCase', 'LiskEphemeralObjectException' => 'Exception', 'LiskFixtureTestCase' => 'PhabricatorTestCase', 'LiskIsolationTestCase' => 'PhabricatorTestCase', 'LiskIsolationTestDAO' => 'LiskDAO', 'LiskIsolationTestDAOException' => 'Exception', 'LiskMigrationIterator' => 'PhutilBufferedIterator', 'ManiphestAction' => 'ManiphestConstants', 'ManiphestAuxiliaryFieldDefaultSpecification' => 'ManiphestAuxiliaryFieldSpecification', 'ManiphestAuxiliaryFieldTypeException' => 'Exception', 'ManiphestAuxiliaryFieldValidationException' => 'Exception', 'ManiphestBatchEditController' => 'ManiphestController', 'ManiphestController' => 'PhabricatorController', 'ManiphestDAO' => 'PhabricatorLiskDAO', 'ManiphestDefaultTaskExtensions' => 'ManiphestTaskExtensions', 'ManiphestEdgeEventListener' => 'PhutilEventListener', 'ManiphestExportController' => 'ManiphestController', 'ManiphestReplyHandler' => 'PhabricatorMailReplyHandler', 'ManiphestReportController' => 'ManiphestController', 'ManiphestSavedQuery' => 'ManiphestDAO', 'ManiphestSavedQueryDeleteController' => 'ManiphestController', 'ManiphestSavedQueryEditController' => 'ManiphestController', 'ManiphestSavedQueryListController' => 'ManiphestController', 'ManiphestSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'ManiphestSubpriorityController' => 'ManiphestController', 'ManiphestTask' => array( 0 => 'ManiphestDAO', 1 => 'PhabricatorMarkupInterface', ), 'ManiphestTaskAuxiliaryStorage' => 'ManiphestDAO', 'ManiphestTaskDescriptionChangeController' => 'ManiphestController', 'ManiphestTaskDescriptionPreviewController' => 'ManiphestController', 'ManiphestTaskDetailController' => 'ManiphestController', 'ManiphestTaskEditController' => 'ManiphestController', 'ManiphestTaskListController' => 'ManiphestController', 'ManiphestTaskListView' => 'ManiphestView', 'ManiphestTaskOwner' => 'ManiphestConstants', 'ManiphestTaskPriority' => 'ManiphestConstants', 'ManiphestTaskProject' => 'ManiphestDAO', 'ManiphestTaskProjectsView' => 'ManiphestView', 'ManiphestTaskQuery' => 'PhabricatorQuery', 'ManiphestTaskStatus' => 'ManiphestConstants', 'ManiphestTaskSubscriber' => 'ManiphestDAO', 'ManiphestTaskSummaryView' => 'ManiphestView', 'ManiphestTransaction' => array( 0 => 'ManiphestDAO', 1 => 'PhabricatorMarkupInterface', ), 'ManiphestTransactionDetailView' => 'ManiphestView', 'ManiphestTransactionEditor' => 'PhabricatorEditor', 'ManiphestTransactionListView' => 'ManiphestView', 'ManiphestTransactionPreviewController' => 'ManiphestController', 'ManiphestTransactionSaveController' => 'ManiphestController', 'ManiphestTransactionType' => 'ManiphestConstants', 'ManiphestView' => 'AphrontView', 'MetaMTANotificationType' => 'MetaMTAConstants', 'OwnersPackageReplyHandler' => 'PhabricatorMailReplyHandler', 'PackageCreateMail' => 'PackageMail', 'PackageDeleteMail' => 'PackageMail', 'PackageModifyMail' => 'PackageMail', 'Phabricator404Controller' => 'PhabricatorController', 'PhabricatorAWSConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAccessLogConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorActionListExample' => 'PhabricatorUIExample', 'PhabricatorActionListView' => 'AphrontView', 'PhabricatorActionView' => 'AphrontView', 'PhabricatorAllCapsTranslation' => 'PhabricatorTranslation', 'PhabricatorAnchorView' => 'AphrontView', 'PhabricatorApplicationApplications' => 'PhabricatorApplication', 'PhabricatorApplicationAudit' => 'PhabricatorApplication', 'PhabricatorApplicationAuth' => 'PhabricatorApplication', 'PhabricatorApplicationCalendar' => 'PhabricatorApplication', 'PhabricatorApplicationConduit' => 'PhabricatorApplication', 'PhabricatorApplicationConfig' => 'PhabricatorApplication', 'PhabricatorApplicationConfigOptions' => 'Phobject', 'PhabricatorApplicationConpherence' => 'PhabricatorApplication', 'PhabricatorApplicationCountdown' => 'PhabricatorApplication', 'PhabricatorApplicationDaemons' => 'PhabricatorApplication', 'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationDifferential' => 'PhabricatorApplication', 'PhabricatorApplicationDiffusion' => 'PhabricatorApplication', 'PhabricatorApplicationDiviner' => 'PhabricatorApplication', 'PhabricatorApplicationDrydock' => 'PhabricatorApplication', 'PhabricatorApplicationFact' => 'PhabricatorApplication', 'PhabricatorApplicationFeed' => 'PhabricatorApplication', 'PhabricatorApplicationFiles' => 'PhabricatorApplication', 'PhabricatorApplicationFlags' => 'PhabricatorApplication', 'PhabricatorApplicationHerald' => 'PhabricatorApplication', 'PhabricatorApplicationLaunchView' => 'AphrontView', 'PhabricatorApplicationMacro' => 'PhabricatorApplication', 'PhabricatorApplicationMailingLists' => 'PhabricatorApplication', 'PhabricatorApplicationManiphest' => 'PhabricatorApplication', 'PhabricatorApplicationMetaMTA' => 'PhabricatorApplication', 'PhabricatorApplicationOwners' => 'PhabricatorApplication', 'PhabricatorApplicationPHID' => 'PhabricatorApplication', 'PhabricatorApplicationPHPAST' => 'PhabricatorApplication', 'PhabricatorApplicationPaste' => 'PhabricatorApplication', 'PhabricatorApplicationPeople' => 'PhabricatorApplication', 'PhabricatorApplicationPhame' => 'PhabricatorApplication', 'PhabricatorApplicationPholio' => 'PhabricatorApplication', 'PhabricatorApplicationPhriction' => 'PhabricatorApplication', 'PhabricatorApplicationPonder' => 'PhabricatorApplication', 'PhabricatorApplicationProject' => 'PhabricatorApplication', 'PhabricatorApplicationRepositories' => 'PhabricatorApplication', 'PhabricatorApplicationSettings' => 'PhabricatorApplication', 'PhabricatorApplicationSlowvote' => 'PhabricatorApplication', 'PhabricatorApplicationStatusView' => 'AphrontView', 'PhabricatorApplicationSubscriptions' => 'PhabricatorApplication', 'PhabricatorApplicationTransaction' => array( 0 => 'PhabricatorLiskDAO', 1 => 'PhabricatorPolicyInterface', ), 'PhabricatorApplicationTransactionComment' => array( 0 => 'PhabricatorLiskDAO', 1 => 'PhabricatorMarkupInterface', 2 => 'PhabricatorPolicyInterface', ), 'PhabricatorApplicationTransactionCommentEditController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionCommentEditor' => 'PhabricatorEditor', 'PhabricatorApplicationTransactionCommentHistoryController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionCommentQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorApplicationTransactionCommentView' => 'AphrontView', 'PhabricatorApplicationTransactionController' => 'PhabricatorController', 'PhabricatorApplicationTransactionEditor' => 'PhabricatorEditor', 'PhabricatorApplicationTransactionFeedStory' => 'PhabricatorFeedStory', 'PhabricatorApplicationTransactionNoEffectException' => 'Exception', 'PhabricatorApplicationTransactionNoEffectResponse' => 'AphrontProxyResponse', 'PhabricatorApplicationTransactionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorApplicationTransactionResponse' => 'AphrontProxyResponse', 'PhabricatorApplicationTransactionView' => 'AphrontView', 'PhabricatorApplicationTransactions' => 'PhabricatorApplication', 'PhabricatorApplicationUIExamples' => 'PhabricatorApplication', 'PhabricatorApplicationUninstallController' => 'PhabricatorApplicationsController', 'PhabricatorApplicationsController' => 'PhabricatorController', 'PhabricatorApplicationsListController' => 'PhabricatorApplicationsController', 'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController', 'PhabricatorAuditComment' => array( 0 => 'PhabricatorAuditDAO', 1 => 'PhabricatorMarkupInterface', ), 'PhabricatorAuditCommentEditor' => 'PhabricatorEditor', 'PhabricatorAuditCommitListView' => 'AphrontView', 'PhabricatorAuditController' => 'PhabricatorController', 'PhabricatorAuditDAO' => 'PhabricatorLiskDAO', 'PhabricatorAuditInlineComment' => array( 0 => 'PhabricatorAuditDAO', 1 => 'PhabricatorInlineCommentInterface', ), 'PhabricatorAuditListController' => 'PhabricatorAuditController', 'PhabricatorAuditListView' => 'AphrontView', 'PhabricatorAuditPreviewController' => 'PhabricatorAuditController', 'PhabricatorAuditReplyHandler' => 'PhabricatorMailReplyHandler', 'PhabricatorAuthController' => 'PhabricatorController', 'PhabricatorAuthenticationConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorBarePageExample' => 'PhabricatorUIExample', 'PhabricatorBarePageView' => 'AphrontPageView', 'PhabricatorBaseEnglishTranslation' => 'PhabricatorTranslation', 'PhabricatorBuiltinPatchList' => 'PhabricatorSQLPatchList', 'PhabricatorButtonsExample' => 'PhabricatorUIExample', 'PhabricatorCacheDAO' => 'PhabricatorLiskDAO', 'PhabricatorCalendarBrowseController' => 'PhabricatorCalendarController', 'PhabricatorCalendarController' => 'PhabricatorController', 'PhabricatorCalendarDAO' => 'PhabricatorLiskDAO', 'PhabricatorCalendarDeleteStatusController' => 'PhabricatorCalendarController', 'PhabricatorCalendarEditStatusController' => 'PhabricatorCalendarController', 'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO', 'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase', 'PhabricatorCalendarViewStatusController' => 'PhabricatorCalendarController', 'PhabricatorChangesetResponse' => 'AphrontProxyResponse', 'PhabricatorChatLogChannelListController' => 'PhabricatorChatLogController', 'PhabricatorChatLogChannelLogController' => 'PhabricatorChatLogController', 'PhabricatorChatLogController' => 'PhabricatorController', 'PhabricatorChatLogDAO' => 'PhabricatorLiskDAO', 'PhabricatorChatLogEvent' => array( 0 => 'PhabricatorChatLogDAO', 1 => 'PhabricatorPolicyInterface', ), 'PhabricatorChatLogEventType' => 'PhabricatorChatLogConstants', 'PhabricatorChatLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorConduitAPIController' => 'PhabricatorConduitController', 'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO', 'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO', 'PhabricatorConduitConsoleController' => 'PhabricatorConduitController', 'PhabricatorConduitController' => 'PhabricatorController', 'PhabricatorConduitDAO' => 'PhabricatorLiskDAO', 'PhabricatorConduitListController' => 'PhabricatorConduitController', 'PhabricatorConduitLogController' => 'PhabricatorConduitController', 'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO', 'PhabricatorConduitTokenController' => 'PhabricatorConduitController', 'PhabricatorConfigAllController' => 'PhabricatorConfigController', 'PhabricatorConfigController' => 'PhabricatorController', 'PhabricatorConfigDatabaseSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigDefaultSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigDictionarySource' => 'PhabricatorConfigSource', 'PhabricatorConfigEditController' => 'PhabricatorConfigController', 'PhabricatorConfigEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorConfigEntry' => 'PhabricatorConfigEntryDAO', 'PhabricatorConfigEntryDAO' => 'PhabricatorLiskDAO', 'PhabricatorConfigFileSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigGroupController' => 'PhabricatorConfigController', 'PhabricatorConfigIssueListController' => 'PhabricatorConfigController', 'PhabricatorConfigIssueViewController' => 'PhabricatorConfigController', 'PhabricatorConfigListController' => 'PhabricatorConfigController', 'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource', 'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow', 'PhabricatorConfigManagementGetWorkflow' => 'PhabricatorConfigManagementWorkflow', 'PhabricatorConfigManagementListWorkflow' => 'PhabricatorConfigManagementWorkflow', 'PhabricatorConfigManagementSetWorkflow' => 'PhabricatorConfigManagementWorkflow', 'PhabricatorConfigManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorConfigOption' => array( 0 => 'Phobject', 1 => 'PhabricatorMarkupInterface', ), 'PhabricatorConfigProxySource' => 'PhabricatorConfigSource', 'PhabricatorConfigResponse' => 'AphrontHTMLResponse', 'PhabricatorConfigStackSource' => 'PhabricatorConfigSource', 'PhabricatorConfigTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorConfigValidationException' => 'Exception', 'PhabricatorContentSourceView' => 'AphrontView', 'PhabricatorController' => 'AphrontController', 'PhabricatorCoreConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorCountdownController' => 'PhabricatorController', 'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO', 'PhabricatorCountdownDeleteController' => 'PhabricatorCountdownController', 'PhabricatorCountdownEditController' => 'PhabricatorCountdownController', 'PhabricatorCountdownListController' => 'PhabricatorCountdownController', 'PhabricatorCountdownViewController' => 'PhabricatorCountdownController', 'PhabricatorCrumbView' => 'AphrontView', 'PhabricatorCrumbsView' => 'AphrontView', 'PhabricatorCursorPagedPolicyAwareQuery' => 'PhabricatorPolicyAwareQuery', 'PhabricatorDaemon' => 'PhutilDaemon', 'PhabricatorDaemonCombinedLogController' => 'PhabricatorDaemonController', 'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController', 'PhabricatorDaemonController' => 'PhabricatorController', 'PhabricatorDaemonDAO' => 'PhabricatorLiskDAO', 'PhabricatorDaemonLog' => 'PhabricatorDaemonDAO', 'PhabricatorDaemonLogEvent' => 'PhabricatorDaemonDAO', 'PhabricatorDaemonLogEventsView' => 'AphrontView', 'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController', 'PhabricatorDaemonLogListView' => 'AphrontView', 'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController', 'PhabricatorDefaultFileStorageEngineSelector' => 'PhabricatorFileStorageEngineSelector', 'PhabricatorDefaultSearchEngineSelector' => 'PhabricatorSearchEngineSelector', 'PhabricatorDeveloperConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorDifferentialConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorDiffusionConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorDirectoryController' => 'PhabricatorController', 'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController', 'PhabricatorDisabledUserController' => 'PhabricatorAuthController', 'PhabricatorDisqusConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorDraft' => 'PhabricatorDraftDAO', 'PhabricatorDraftDAO' => 'PhabricatorLiskDAO', 'PhabricatorEdgeConfig' => 'PhabricatorEdgeConstants', 'PhabricatorEdgeCycleException' => 'Exception', 'PhabricatorEdgeEditor' => 'PhabricatorEditor', 'PhabricatorEdgeGraph' => 'AbstractDirectedGraph', 'PhabricatorEdgeQuery' => 'PhabricatorQuery', 'PhabricatorEdgeTestCase' => 'PhabricatorTestCase', 'PhabricatorEditor' => 'Phobject', 'PhabricatorEmailLoginController' => 'PhabricatorAuthController', 'PhabricatorEmailTokenController' => 'PhabricatorAuthController', 'PhabricatorEmailVerificationController' => 'PhabricatorPeopleController', 'PhabricatorEnglishTranslation' => 'PhabricatorBaseEnglishTranslation', 'PhabricatorEnvTestCase' => 'PhabricatorTestCase', 'PhabricatorErrorExample' => 'PhabricatorUIExample', 'PhabricatorEvent' => 'PhutilEvent', 'PhabricatorEventType' => 'PhutilEventType', 'PhabricatorExampleEventListener' => 'PhutilEventListener', 'PhabricatorExtendingPhabricatorConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorFacebookConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorFactAggregate' => 'PhabricatorFactDAO', 'PhabricatorFactChartController' => 'PhabricatorFactController', 'PhabricatorFactController' => 'PhabricatorController', 'PhabricatorFactCountEngine' => 'PhabricatorFactEngine', 'PhabricatorFactCursor' => 'PhabricatorFactDAO', 'PhabricatorFactDAO' => 'PhabricatorLiskDAO', 'PhabricatorFactDaemon' => 'PhabricatorDaemon', 'PhabricatorFactHomeController' => 'PhabricatorFactController', 'PhabricatorFactLastUpdatedEngine' => 'PhabricatorFactEngine', 'PhabricatorFactManagementAnalyzeWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementCursorsWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementDestroyWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementListWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementStatusWorkflow' => 'PhabricatorFactManagementWorkflow', 'PhabricatorFactManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorFactRaw' => 'PhabricatorFactDAO', 'PhabricatorFactSimpleSpec' => 'PhabricatorFactSpec', 'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator', 'PhabricatorFeedConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorFeedController' => 'PhabricatorController', 'PhabricatorFeedDAO' => 'PhabricatorLiskDAO', 'PhabricatorFeedMainController' => 'PhabricatorFeedController', 'PhabricatorFeedPublicStreamController' => 'PhabricatorFeedController', 'PhabricatorFeedQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorFeedStory' => 'PhabricatorPolicyInterface', 'PhabricatorFeedStoryAggregate' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryAudit' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryCommit' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryData' => 'PhabricatorFeedDAO', 'PhabricatorFeedStoryDifferential' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryDifferentialAggregate' => 'PhabricatorFeedStoryAggregate', 'PhabricatorFeedStoryManiphest' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryManiphestAggregate' => 'PhabricatorFeedStoryAggregate', 'PhabricatorFeedStoryNotification' => 'PhabricatorFeedDAO', 'PhabricatorFeedStoryPhriction' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryProject' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryReference' => 'PhabricatorFeedDAO', 'PhabricatorFeedStoryStatus' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryTypeConstants' => 'PhabricatorFeedConstants', 'PhabricatorFeedStoryView' => 'PhabricatorFeedView', 'PhabricatorFeedView' => 'AphrontView', 'PhabricatorFile' => array( 0 => 'PhabricatorFileDAO', 1 => 'PhabricatorPolicyInterface', ), 'PhabricatorFileController' => 'PhabricatorController', 'PhabricatorFileDAO' => 'PhabricatorLiskDAO', 'PhabricatorFileDataController' => 'PhabricatorFileController', 'PhabricatorFileDeleteController' => 'PhabricatorFileController', 'PhabricatorFileDropUploadController' => 'PhabricatorFileController', 'PhabricatorFileImageMacro' => array( 0 => 'PhabricatorFileDAO', 1 => 'PhabricatorSubscribableInterface', ), 'PhabricatorFileInfoController' => 'PhabricatorFileController', 'PhabricatorFileLinkListView' => 'AphrontView', 'PhabricatorFileLinkView' => 'AphrontView', 'PhabricatorFileListController' => 'PhabricatorFileController', 'PhabricatorFileQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorFileShortcutController' => 'PhabricatorFileController', 'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO', 'PhabricatorFileStorageConfigurationException' => 'Exception', 'PhabricatorFileTransformController' => 'PhabricatorFileController', 'PhabricatorFileUploadController' => 'PhabricatorFileController', 'PhabricatorFileUploadException' => 'Exception', 'PhabricatorFilesConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorFilesManagementEnginesWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementMetadataWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementMigrateWorkflow' => 'PhabricatorFilesManagementWorkflow', 'PhabricatorFilesManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorFlag' => 'PhabricatorFlagDAO', 'PhabricatorFlagColor' => 'PhabricatorFlagConstants', 'PhabricatorFlagController' => 'PhabricatorController', 'PhabricatorFlagDAO' => 'PhabricatorLiskDAO', 'PhabricatorFlagDeleteController' => 'PhabricatorFlagController', 'PhabricatorFlagEditController' => 'PhabricatorFlagController', 'PhabricatorFlagListController' => 'PhabricatorFlagController', 'PhabricatorFlagListView' => 'AphrontView', 'PhabricatorFlagsUIEventListener' => 'PhutilEventListener', 'PhabricatorFormExample' => 'PhabricatorUIExample', 'PhabricatorGarbageCollectorConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorGarbageCollectorDaemon' => 'PhabricatorDaemon', 'PhabricatorGitHubConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorGlobalLock' => 'PhutilLock', 'PhabricatorGlobalUploadTargetView' => 'AphrontView', 'PhabricatorGoogleConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorHashTestCase' => 'PhabricatorTestCase', 'PhabricatorHeaderView' => 'AphrontView', 'PhabricatorHelpController' => 'PhabricatorController', 'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController', 'PhabricatorIRCBot' => 'PhabricatorDaemon', 'PhabricatorIRCDifferentialNotificationHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCFeedNotificationHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCLogHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCMacroHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCObjectNameHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCProtocolHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCSymbolHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCWhatsNewHandler' => 'PhabricatorIRCHandler', 'PhabricatorInfrastructureTestCase' => 'PhabricatorTestCase', 'PhabricatorInlineCommentController' => 'PhabricatorController', 'PhabricatorInlineCommentInterface' => 'PhabricatorMarkupInterface', 'PhabricatorInlineCommentPreviewController' => 'PhabricatorController', 'PhabricatorInlineSummaryView' => 'AphrontView', 'PhabricatorJavelinLinter' => 'ArcanistLinter', 'PhabricatorKeyValueDatabaseCache' => 'PhutilKeyValueCache', 'PhabricatorLDAPConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorLDAPLoginController' => 'PhabricatorAuthController', 'PhabricatorLDAPRegistrationController' => 'PhabricatorAuthController', 'PhabricatorLDAPUnknownUserException' => 'Exception', 'PhabricatorLDAPUnlinkController' => 'PhabricatorAuthController', 'PhabricatorLintEngine' => 'PhutilLintEngine', 'PhabricatorLiskDAO' => 'LiskDAO', 'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase', 'PhabricatorLoginController' => 'PhabricatorAuthController', 'PhabricatorLoginValidateController' => 'PhabricatorAuthController', 'PhabricatorLogoutController' => 'PhabricatorAuthController', 'PhabricatorMacroCommentController' => 'PhabricatorMacroController', 'PhabricatorMacroConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMacroController' => 'PhabricatorController', 'PhabricatorMacroDisableController' => 'PhabricatorMacroController', 'PhabricatorMacroEditController' => 'PhabricatorMacroController', 'PhabricatorMacroEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorMacroListController' => 'PhabricatorMacroController', 'PhabricatorMacroMemeController' => 'PhabricatorMacroController', 'PhabricatorMacroMemeDialogController' => 'PhabricatorMacroController', 'PhabricatorMacroReplyHandler' => 'PhabricatorMailReplyHandler', 'PhabricatorMacroTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorMacroTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorMacroViewController' => 'PhabricatorMacroController', 'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter', 'PhabricatorMailImplementationPHPMailerAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailingListsController' => 'PhabricatorController', 'PhabricatorMailingListsEditController' => 'PhabricatorMailingListsController', 'PhabricatorMailingListsListController' => 'PhabricatorMailingListsController', 'PhabricatorMainMenuGroupView' => 'AphrontView', 'PhabricatorMainMenuIconView' => 'AphrontView', 'PhabricatorMainMenuSearchView' => 'AphrontView', 'PhabricatorMainMenuView' => 'AphrontView', 'PhabricatorManiphestConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMarkupCache' => 'PhabricatorCacheDAO', 'PhabricatorMenuItemView' => 'AphrontTagView', 'PhabricatorMenuView' => 'AphrontTagView', + 'PhabricatorMenuViewTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMetaMTAController' => 'PhabricatorController', 'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO', 'PhabricatorMetaMTAEmailBodyParserTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAListController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAMailBodyTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailingList' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAReceivedListController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTASendController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTASendGridReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAViewController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAWorker' => 'PhabricatorWorker', 'PhabricatorMustVerifyEmailController' => 'PhabricatorAuthController', 'PhabricatorMySQLConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorNotificationClearController' => 'PhabricatorNotificationController', 'PhabricatorNotificationConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorNotificationController' => 'PhabricatorController', 'PhabricatorNotificationIndividualController' => 'PhabricatorNotificationController', 'PhabricatorNotificationListController' => 'PhabricatorNotificationController', 'PhabricatorNotificationPanelController' => 'PhabricatorNotificationController', 'PhabricatorNotificationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorNotificationStatusController' => 'PhabricatorNotificationController', 'PhabricatorOAuthClientAuthorization' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthClientAuthorizationBaseController' => 'PhabricatorOAuthServerController', 'PhabricatorOAuthClientAuthorizationDeleteController' => 'PhabricatorOAuthClientAuthorizationBaseController', 'PhabricatorOAuthClientAuthorizationEditController' => 'PhabricatorOAuthClientAuthorizationBaseController', 'PhabricatorOAuthClientAuthorizationListController' => 'PhabricatorOAuthClientAuthorizationBaseController', 'PhabricatorOAuthClientAuthorizationQuery' => 'PhabricatorOffsetPagedQuery', 'PhabricatorOAuthClientBaseController' => 'PhabricatorOAuthServerController', 'PhabricatorOAuthClientDeleteController' => 'PhabricatorOAuthClientBaseController', 'PhabricatorOAuthClientEditController' => 'PhabricatorOAuthClientBaseController', 'PhabricatorOAuthClientListController' => 'PhabricatorOAuthClientBaseController', 'PhabricatorOAuthClientViewController' => 'PhabricatorOAuthClientBaseController', 'PhabricatorOAuthDefaultRegistrationController' => 'PhabricatorOAuthRegistrationController', 'PhabricatorOAuthDiagnosticsController' => 'PhabricatorAuthController', 'PhabricatorOAuthFailureView' => 'AphrontView', 'PhabricatorOAuthLoginController' => 'PhabricatorAuthController', 'PhabricatorOAuthProviderDisqus' => 'PhabricatorOAuthProvider', 'PhabricatorOAuthProviderException' => 'Exception', 'PhabricatorOAuthProviderFacebook' => 'PhabricatorOAuthProvider', 'PhabricatorOAuthProviderGitHub' => 'PhabricatorOAuthProvider', 'PhabricatorOAuthProviderGoogle' => 'PhabricatorOAuthProvider', 'PhabricatorOAuthProviderPhabricator' => 'PhabricatorOAuthProvider', 'PhabricatorOAuthRegistrationController' => 'PhabricatorAuthController', 'PhabricatorOAuthResponse' => 'AphrontResponse', 'PhabricatorOAuthServerAccessToken' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthServerAuthController' => 'PhabricatorAuthController', 'PhabricatorOAuthServerAuthorizationCode' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthServerClient' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthServerClientQuery' => 'PhabricatorOffsetPagedQuery', 'PhabricatorOAuthServerController' => 'PhabricatorController', 'PhabricatorOAuthServerDAO' => 'PhabricatorLiskDAO', 'PhabricatorOAuthServerTestCase' => 'PhabricatorTestCase', 'PhabricatorOAuthServerTestController' => 'PhabricatorOAuthServerController', 'PhabricatorOAuthServerTokenController' => 'PhabricatorAuthController', 'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController', 'PhabricatorObjectHandleStatus' => 'PhabricatorObjectHandleConstants', 'PhabricatorObjectItemListView' => 'AphrontView', 'PhabricatorObjectItemView' => 'AphrontView', 'PhabricatorObjectListView' => 'AphrontView', 'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery', 'PhabricatorOwnersConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorOwnersController' => 'PhabricatorController', 'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO', 'PhabricatorOwnersDeleteController' => 'PhabricatorOwnersController', 'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController', 'PhabricatorOwnersEditController' => 'PhabricatorOwnersController', 'PhabricatorOwnersListController' => 'PhabricatorOwnersController', 'PhabricatorOwnersOwner' => 'PhabricatorOwnersDAO', 'PhabricatorOwnersPackage' => array( 0 => 'PhabricatorOwnersDAO', 1 => 'PhabricatorPolicyInterface', ), 'PhabricatorOwnersPackageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorOwnersPackageTestCase' => 'PhabricatorTestCase', 'PhabricatorOwnersPath' => 'PhabricatorOwnersDAO', 'PhabricatorPHDConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPHIDConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPHIDController' => 'PhabricatorController', 'PhabricatorPHIDLookupController' => 'PhabricatorPHIDController', 'PhabricatorPHPMailerConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPaste' => array( 0 => 'PhabricatorPasteDAO', 1 => 'PhabricatorPolicyInterface', ), 'PhabricatorPasteController' => 'PhabricatorController', 'PhabricatorPasteDAO' => 'PhabricatorLiskDAO', 'PhabricatorPasteEditController' => 'PhabricatorPasteController', 'PhabricatorPasteListController' => 'PhabricatorPasteController', 'PhabricatorPasteQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPasteViewController' => 'PhabricatorPasteController', 'PhabricatorPeopleController' => 'PhabricatorController', 'PhabricatorPeopleEditController' => 'PhabricatorPeopleController', 'PhabricatorPeopleLdapController' => 'PhabricatorPeopleController', 'PhabricatorPeopleListController' => 'PhabricatorPeopleController', 'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', 'PhabricatorPeopleQuery' => 'PhabricatorOffsetPagedQuery', 'PhabricatorPhabricatorOAuthConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPhameConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPholioConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPhrictionConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPinboardItemView' => 'AphrontView', 'PhabricatorPinboardView' => 'AphrontView', 'PhabricatorPolicies' => 'PhabricatorPolicyConstants', 'PhabricatorPolicyAwareQuery' => 'PhabricatorOffsetPagedQuery', 'PhabricatorPolicyAwareTestQuery' => 'PhabricatorPolicyAwareQuery', 'PhabricatorPolicyCapability' => 'PhabricatorPolicyConstants', 'PhabricatorPolicyConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPolicyException' => 'Exception', 'PhabricatorPolicyQuery' => 'PhabricatorQuery', 'PhabricatorPolicyTestCase' => 'PhabricatorTestCase', 'PhabricatorPolicyTestObject' => 'PhabricatorPolicyInterface', 'PhabricatorPolicyType' => 'PhabricatorPolicyConstants', 'PhabricatorProfileHeaderView' => 'AphrontView', 'PhabricatorProject' => array( 0 => 'PhabricatorProjectDAO', 1 => 'PhabricatorPolicyInterface', ), 'PhabricatorProjectController' => 'PhabricatorController', 'PhabricatorProjectCreateController' => 'PhabricatorProjectController', 'PhabricatorProjectDAO' => 'PhabricatorLiskDAO', 'PhabricatorProjectEditor' => 'PhabricatorEditor', 'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase', 'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersEditController' => 'PhabricatorProjectController', 'PhabricatorProjectNameCollisionException' => 'Exception', 'PhabricatorProjectProfile' => 'PhabricatorProjectDAO', 'PhabricatorProjectProfileController' => 'PhabricatorProjectController', 'PhabricatorProjectProfileEditController' => 'PhabricatorProjectController', 'PhabricatorProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProjectTransaction' => 'PhabricatorProjectDAO', 'PhabricatorProjectTransactionType' => 'PhabricatorProjectConstants', 'PhabricatorProjectUpdateController' => 'PhabricatorProjectController', 'PhabricatorPropertyListExample' => 'PhabricatorUIExample', 'PhabricatorPropertyListView' => 'AphrontView', 'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorRedirectController' => 'PhabricatorController', 'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController', 'PhabricatorRemarkupControl' => 'AphrontFormTextAreaControl', 'PhabricatorRemarkupRuleCountdown' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName', 'PhabricatorRemarkupRuleDifferentialHandle' => 'PhabricatorRemarkupRuleObjectHandle', 'PhabricatorRemarkupRuleDiffusion' => 'PhabricatorRemarkupRuleObjectName', 'PhabricatorRemarkupRuleEmbedFile' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleImageMacro' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleManiphest' => 'PhabricatorRemarkupRuleObjectName', 'PhabricatorRemarkupRuleManiphestHandle' => 'PhabricatorRemarkupRuleObjectHandle', 'PhabricatorRemarkupRuleMeme' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleMention' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleObjectHandle' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleObjectName' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRulePaste' => 'PhabricatorRemarkupRuleObjectName', 'PhabricatorRemarkupRulePhriction' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleYoutube' => 'PhutilRemarkupRule', 'PhabricatorRepository' => array( 0 => 'PhabricatorRepositoryDAO', 1 => 'PhabricatorPolicyInterface', ), 'PhabricatorRepositoryArcanistProject' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryArcanistProjectDeleteController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryArcanistProjectEditController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryAuditRequest' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryBranch' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCommit' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitOwnersWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker', 'PhabricatorRepositoryCommitSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'PhabricatorRepositoryConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorRepositoryController' => 'PhabricatorController', 'PhabricatorRepositoryCreateController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO', 'PhabricatorRepositoryDeleteController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryEditController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositoryListController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryManagementDeleteWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementDiscoverWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementListWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementPullWorkflow' => 'PhabricatorRepositoryManagementWorkflow', 'PhabricatorRepositoryManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositoryPullLocalDaemon' => 'PhabricatorDaemon', 'PhabricatorRepositoryPullLocalDaemonTestCase' => 'PhabricatorTestCase', 'PhabricatorRepositoryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorRepositoryShortcut' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryTestCase' => 'PhabricatorTestCase', 'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorSSHWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorSearchAttachController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchBaseController' => 'PhabricatorController', 'PhabricatorSearchConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSearchController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchDAO' => 'PhabricatorLiskDAO', 'PhabricatorSearchDocument' => 'PhabricatorSearchDAO', 'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO', 'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO', 'PhabricatorSearchEngineElastic' => 'PhabricatorSearchEngine', 'PhabricatorSearchEngineMySQL' => 'PhabricatorSearchEngine', 'PhabricatorSearchManagementIndexWorkflow' => 'PhabricatorSearchManagementWorkflow', 'PhabricatorSearchManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorSearchQuery' => 'PhabricatorSearchDAO', 'PhabricatorSearchResultView' => 'AphrontView', 'PhabricatorSearchSelectController' => 'PhabricatorSearchBaseController', 'PhabricatorSecurityConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSendGridConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorSettingsAdjustController' => 'PhabricatorController', 'PhabricatorSettingsMainController' => 'PhabricatorController', 'PhabricatorSettingsPanelAccount' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelConduit' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelDisplayPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelEmailAddresses' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelEmailPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelHomePreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelLDAP' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelOAuth' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelPassword' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelProfile' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel', 'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel', 'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckBaseURI' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckDatabase' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckExtensions' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckExtraConfig' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckFacebook' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckGD' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckInvalidConfig' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckMail' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckMySQL' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckPHPConfig' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckPath' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckStorage' => 'PhabricatorSetupCheck', 'PhabricatorSetupCheckTimezone' => 'PhabricatorSetupCheck', 'PhabricatorSetupIssueExample' => 'PhabricatorUIExample', 'PhabricatorSetupIssueView' => 'AphrontView', 'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvoteController' => 'PhabricatorController', 'PhabricatorSlowvoteCreateController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteDAO' => 'PhabricatorLiskDAO', 'PhabricatorSlowvoteListController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvotePoll' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController', 'PhabricatorSlugTestCase' => 'PhabricatorTestCase', 'PhabricatorSortTableExample' => 'PhabricatorUIExample', 'PhabricatorSourceCodeView' => 'AphrontView', 'PhabricatorStandardPageView' => 'PhabricatorBarePageView', 'PhabricatorStatusController' => 'PhabricatorController', 'PhabricatorStorageManagementDatabasesWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDestroyWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementDumpWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementStatusWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementUpgradeWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementWorkflow' => 'PhutilArgumentWorkflow', 'PhabricatorSubscribersQuery' => 'PhabricatorQuery', 'PhabricatorSubscriptionsEditController' => 'PhabricatorController', 'PhabricatorSubscriptionsEditor' => 'PhabricatorEditor', 'PhabricatorSubscriptionsUIEventListener' => 'PhutilEventListener', 'PhabricatorSymbolNameLinter' => 'ArcanistXHPASTLintNamingHook', 'PhabricatorSyntaxHighlightingConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorTagExample' => 'PhabricatorUIExample', 'PhabricatorTagView' => 'AphrontView', 'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon', 'PhabricatorTestCase' => 'ArcanistPhutilTestCase', 'PhabricatorTestWorker' => 'PhabricatorWorker', 'PhabricatorTimelineCursor' => 'PhabricatorTimelineDAO', 'PhabricatorTimelineDAO' => 'PhabricatorLiskDAO', 'PhabricatorTimelineEvent' => 'PhabricatorTimelineDAO', 'PhabricatorTimelineEventData' => 'PhabricatorTimelineDAO', 'PhabricatorTimelineEventView' => 'AphrontView', 'PhabricatorTimelineExample' => 'PhabricatorUIExample', 'PhabricatorTimelineIterator' => 'Iterator', 'PhabricatorTimelineView' => 'AphrontView', 'PhabricatorTimer' => 'PhabricatorCountdownDAO', 'PhabricatorTransactionView' => 'AphrontView', 'PhabricatorTransformedFile' => 'PhabricatorFileDAO', 'PhabricatorTranslationsConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorTrivialTestCase' => 'PhabricatorTestCase', 'PhabricatorTypeaheadCommonDatasourceController' => 'PhabricatorTypeaheadDatasourceController', 'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController', 'PhabricatorUIExampleRenderController' => 'PhabricatorController', 'PhabricatorUIListFilterExample' => 'PhabricatorUIExample', 'PhabricatorUINotificationExample' => 'PhabricatorUIExample', 'PhabricatorUIPagerExample' => 'PhabricatorUIExample', 'PhabricatorUITooltipExample' => 'PhabricatorUIExample', 'PhabricatorUnitsTestCase' => 'PhabricatorTestCase', 'PhabricatorUser' => array( 0 => 'PhabricatorUserDAO', 1 => 'PhutilPerson', ), 'PhabricatorUserDAO' => 'PhabricatorLiskDAO', 'PhabricatorUserEditor' => 'PhabricatorEditor', 'PhabricatorUserEmail' => 'PhabricatorUserDAO', 'PhabricatorUserLDAPInfo' => 'PhabricatorUserDAO', 'PhabricatorUserLog' => 'PhabricatorUserDAO', 'PhabricatorUserOAuthInfo' => 'PhabricatorUserDAO', 'PhabricatorUserPreferences' => 'PhabricatorUserDAO', 'PhabricatorUserProfile' => 'PhabricatorUserDAO', 'PhabricatorUserSSHKey' => 'PhabricatorUserDAO', 'PhabricatorUserSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'PhabricatorUserStatus' => 'PhabricatorUserDAO', 'PhabricatorUserStatusInvalidEpochException' => 'Exception', 'PhabricatorUserStatusOverlapException' => 'Exception', 'PhabricatorUserTestCase' => 'PhabricatorTestCase', 'PhabricatorWorkerActiveTask' => 'PhabricatorWorkerTask', 'PhabricatorWorkerArchiveTask' => 'PhabricatorWorkerTask', 'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO', 'PhabricatorWorkerLeaseQuery' => 'PhabricatorQuery', 'PhabricatorWorkerPermanentFailureException' => 'Exception', 'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO', 'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO', 'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController', 'PhabricatorWorkerTaskUpdateController' => 'PhabricatorDaemonController', 'PhabricatorWorkerTestCase' => 'PhabricatorTestCase', 'PhabricatorXHPASTViewController' => 'PhabricatorController', 'PhabricatorXHPASTViewDAO' => 'PhabricatorLiskDAO', 'PhabricatorXHPASTViewFrameController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewFramesetController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewInputController' => 'PhabricatorXHPASTViewPanelController', 'PhabricatorXHPASTViewPanelController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewParseTree' => 'PhabricatorXHPASTViewDAO', 'PhabricatorXHPASTViewRunController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewStreamController' => 'PhabricatorXHPASTViewPanelController', 'PhabricatorXHPASTViewTreeController' => 'PhabricatorXHPASTViewPanelController', 'PhabricatorXHProfController' => 'PhabricatorController', 'PhabricatorXHProfDAO' => 'PhabricatorLiskDAO', 'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController', 'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileView' => 'AphrontView', 'PhabricatorXHProfSample' => 'PhabricatorXHProfDAO', 'PhabricatorXHProfSampleListController' => 'PhabricatorXHProfController', 'PhabricatorXHProfSampleListView' => 'AphrontView', 'PhameBasicBlogSkin' => 'PhameBlogSkin', 'PhameBasicTemplateBlogSkin' => 'PhameBasicBlogSkin', 'PhameBlog' => array( 0 => 'PhameDAO', 1 => 'PhabricatorPolicyInterface', 2 => 'PhabricatorMarkupInterface', ), 'PhameBlogDeleteController' => 'PhameController', 'PhameBlogEditController' => 'PhameController', 'PhameBlogFeedController' => 'PhameController', 'PhameBlogListController' => 'PhameController', 'PhameBlogLiveController' => 'PhameController', 'PhameBlogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhameBlogSkin' => 'PhabricatorController', 'PhameBlogViewController' => 'PhameController', 'PhameController' => 'PhabricatorController', 'PhameDAO' => 'PhabricatorLiskDAO', 'PhamePost' => array( 0 => 'PhameDAO', 1 => 'PhabricatorPolicyInterface', 2 => 'PhabricatorMarkupInterface', ), 'PhamePostDeleteController' => 'PhameController', 'PhamePostEditController' => 'PhameController', 'PhamePostFramedController' => 'PhameController', 'PhamePostListController' => 'PhameController', 'PhamePostNewController' => 'PhameController', 'PhamePostNotLiveController' => 'PhameController', 'PhamePostPreviewController' => 'PhameController', 'PhamePostPublishController' => 'PhameController', 'PhamePostQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhamePostUnpublishController' => 'PhameController', 'PhamePostView' => 'AphrontView', 'PhamePostViewController' => 'PhameController', 'PhameResourceController' => 'CelerityResourceController', 'PholioController' => 'PhabricatorController', 'PholioDAO' => 'PhabricatorLiskDAO', 'PholioImage' => array( 0 => 'PholioDAO', 1 => 'PhabricatorMarkupInterface', ), 'PholioMock' => array( 0 => 'PholioDAO', 1 => 'PhabricatorMarkupInterface', 2 => 'PhabricatorPolicyInterface', 3 => 'PhabricatorSubscribableInterface', ), 'PholioMockCommentController' => 'PholioController', 'PholioMockEditController' => 'PholioController', 'PholioMockEditor' => 'PhabricatorApplicationTransactionEditor', 'PholioMockImagesView' => 'AphrontView', 'PholioMockListController' => 'PholioController', 'PholioMockQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PholioMockViewController' => 'PholioController', 'PholioReplyHandler' => 'PhabricatorMailReplyHandler', 'PholioSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'PholioTransaction' => 'PhabricatorApplicationTransaction', 'PholioTransactionComment' => 'PhabricatorApplicationTransactionComment', 'PholioTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PholioTransactionType' => 'PholioConstants', 'PhortuneMonthYearExpiryControl' => 'AphrontFormControl', 'PhortuneStripeBaseController' => 'PhabricatorController', 'PhortuneStripePaymentFormView' => 'AphrontView', 'PhortuneStripeTestPaymentFormController' => 'PhortuneStripeBaseController', 'PhrictionActionConstants' => 'PhrictionConstants', 'PhrictionChangeType' => 'PhrictionConstants', 'PhrictionContent' => array( 0 => 'PhrictionDAO', 1 => 'PhabricatorMarkupInterface', ), 'PhrictionController' => 'PhabricatorController', 'PhrictionDAO' => 'PhabricatorLiskDAO', 'PhrictionDeleteController' => 'PhrictionController', 'PhrictionDiffController' => 'PhrictionController', 'PhrictionDocument' => array( 0 => 'PhrictionDAO', 1 => 'PhabricatorPolicyInterface', ), 'PhrictionDocumentController' => 'PhrictionController', 'PhrictionDocumentEditor' => 'PhabricatorEditor', 'PhrictionDocumentPreviewController' => 'PhrictionController', 'PhrictionDocumentStatus' => 'PhrictionConstants', 'PhrictionDocumentTestCase' => 'PhabricatorTestCase', 'PhrictionEditController' => 'PhrictionController', 'PhrictionHistoryController' => 'PhrictionController', 'PhrictionListController' => 'PhrictionController', 'PhrictionNewController' => 'PhrictionController', 'PhrictionSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'PonderAddAnswerView' => 'AphrontView', 'PonderAddCommentView' => 'AphrontView', 'PonderAnswer' => array( 0 => 'PonderDAO', 1 => 'PhabricatorMarkupInterface', 2 => 'PonderVotableInterface', ), 'PonderAnswerEditor' => 'PhabricatorEditor', 'PonderAnswerListView' => 'AphrontView', 'PonderAnswerPreviewController' => 'PonderController', 'PonderAnswerQuery' => 'PhabricatorOffsetPagedQuery', 'PonderAnswerSaveController' => 'PonderController', 'PonderAnswerViewController' => 'PonderController', 'PonderAnsweredMail' => 'PonderMail', 'PonderComment' => array( 0 => 'PonderDAO', 1 => 'PhabricatorMarkupInterface', ), 'PonderCommentEditor' => 'PhabricatorEditor', 'PonderCommentListView' => 'AphrontView', 'PonderCommentMail' => 'PonderMail', 'PonderCommentQuery' => 'PhabricatorQuery', 'PonderCommentSaveController' => 'PonderController', 'PonderController' => 'PhabricatorController', 'PonderDAO' => 'PhabricatorLiskDAO', 'PonderFeedController' => 'PonderController', 'PonderMentionMail' => 'PonderMail', 'PonderPostBodyView' => 'AphrontView', 'PonderQuestion' => array( 0 => 'PonderDAO', 1 => 'PhabricatorMarkupInterface', 2 => 'PonderVotableInterface', 3 => 'PhabricatorSubscribableInterface', 4 => 'PhabricatorPolicyInterface', ), 'PonderQuestionAskController' => 'PonderController', 'PonderQuestionDetailView' => 'AphrontView', 'PonderQuestionEditor' => 'PhabricatorEditor', 'PonderQuestionPreviewController' => 'PonderController', 'PonderQuestionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PonderQuestionSummaryView' => 'AphrontView', 'PonderQuestionViewController' => 'PonderController', 'PonderReplyHandler' => 'PhabricatorMailReplyHandler', 'PonderRuleQuestion' => 'PhabricatorRemarkupRuleObjectName', 'PonderSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'PonderUserProfileView' => 'AphrontView', 'PonderVotableView' => 'AphrontView', 'PonderVoteEditor' => 'PhabricatorEditor', 'PonderVoteSaveController' => 'PonderController', 'QueryFormattingTestCase' => 'PhabricatorTestCase', ), )); diff --git a/src/aphront/AphrontRequest.php b/src/aphront/AphrontRequest.php index c7a659c30..68c0c16b1 100644 --- a/src/aphront/AphrontRequest.php +++ b/src/aphront/AphrontRequest.php @@ -1,413 +1,433 @@ host = $host; $this->path = $path; } final public function setApplicationConfiguration( $application_configuration) { $this->applicationConfiguration = $application_configuration; return $this; } final public function getApplicationConfiguration() { return $this->applicationConfiguration; } final public function setPath($path) { $this->path = $path; return $this; } final public function getPath() { return $this->path; } final public function getHost() { // The "Host" header may include a port number, or may be a malicious // header in the form "realdomain.com:ignored@evil.com". Invoke the full // parser to extract the real domain correctly. See here for coverage of // a similar issue in Django: // // https://www.djangoproject.com/weblog/2012/oct/17/security/ $uri = new PhutilURI('http://'.$this->host); return $uri->getDomain(); } /* -( Accessing Request Data )--------------------------------------------- */ /** * @task data */ final public function setRequestData(array $request_data) { $this->requestData = $request_data; return $this; } /** * @task data */ final public function getRequestData() { return $this->requestData; } /** * @task data */ final public function getInt($name, $default = null) { if (isset($this->requestData[$name])) { return (int)$this->requestData[$name]; } else { return $default; } } /** * @task data */ final public function getBool($name, $default = null) { if (isset($this->requestData[$name])) { if ($this->requestData[$name] === 'true') { return true; } else if ($this->requestData[$name] === 'false') { return false; } else { return (bool)$this->requestData[$name]; } } else { return $default; } } /** * @task data */ final public function getStr($name, $default = null) { if (isset($this->requestData[$name])) { $str = (string)$this->requestData[$name]; // Normalize newline craziness. $str = str_replace( array("\r\n", "\r"), array("\n", "\n"), $str); return $str; } else { return $default; } } /** * @task data */ final public function getArr($name, $default = array()) { if (isset($this->requestData[$name]) && is_array($this->requestData[$name])) { return $this->requestData[$name]; } else { return $default; } } /** * @task data */ final public function getStrList($name, $default = array()) { if (!isset($this->requestData[$name])) { return $default; } $list = $this->getStr($name); $list = preg_split('/[\s,]+/', $list, $limit = -1, PREG_SPLIT_NO_EMPTY); return $list; } /** * @task data */ final public function getExists($name) { return array_key_exists($name, $this->requestData); } final public function getFileExists($name) { return isset($_FILES[$name]) && (idx($_FILES[$name], 'error') !== UPLOAD_ERR_NO_FILE); } final public function isHTTPPost() { return ($_SERVER['REQUEST_METHOD'] == 'POST'); } final public function isAjax() { return $this->getExists(self::TYPE_AJAX); } final public function isJavelinWorkflow() { return $this->getExists(self::TYPE_WORKFLOW); } final public function isConduit() { return $this->getExists(self::TYPE_CONDUIT); } public static function getCSRFTokenName() { return '__csrf__'; } public static function getCSRFHeaderName() { return 'X-Phabricator-Csrf'; } final public function validateCSRF() { $token_name = self::getCSRFTokenName(); $token = $this->getStr($token_name); // No token in the request, check the HTTP header which is added for Ajax // requests. if (empty($token)) { // PHP mangles HTTP headers by uppercasing them and replacing hyphens with // underscores, then prepending 'HTTP_'. $php_index = self::getCSRFHeaderName(); $php_index = strtoupper($php_index); $php_index = str_replace('-', '_', $php_index); $php_index = 'HTTP_'.$php_index; $token = idx($_SERVER, $php_index); } $valid = $this->getUser()->validateCSRFToken($token); if (!$valid) { // Add some diagnostic details so we can figure out if some CSRF issues // are JS problems or people accessing Ajax URIs directly with their // browsers. if ($token) { $token_info = "with an invalid CSRF token"; } else { $token_info = "without a CSRF token"; } if ($this->isAjax()) { $more_info = "(This was an Ajax request, {$token_info}.)"; } else { $more_info = "(This was a web request, {$token_info}.)"; } + // Give a more detailed explanation of how to avoid the exception + // in developer mode. + if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) { + $more_info = $more_info . + "To avoid this error, use phabricator_form() to construct forms. " . + "If you are already using phabricator_form(), make sure the form " . + "'action' uses a relative URI (i.e., begins with a '/'). Forms " . + "using absolute URIs do not include CSRF tokens, to prevent " . + "leaking tokens to external sites.\n\n" . + "If this page performs writes which do not require CSRF " . + "protection (usually, filling caches or logging), you can use " . + "AphrontWriteGuard::beginScopedUnguardedWrites() to temporarily " . + "bypass CSRF protection while writing. You should use this only " . + "for writes which can not be protected with normal CSRF " . + "mechanisms.\n\n" . + "Some UI elements (like PhabricatorActionListView) also have " . + "methods which will allow you to render links as forms (like " . + "setRenderAsForm(true))."; + } + // This should only be able to happen if you load a form, pull your // internet for 6 hours, and then reconnect and immediately submit, // but give the user some indication of what happened since the workflow // is incredibly confusing otherwise. throw new AphrontCSRFException( "The form you just submitted did not include a valid CSRF token. ". "This token is a technical security measure which prevents a ". "certain type of login hijacking attack. However, the token can ". "become invalid if you leave a page open for more than six hours ". "without a connection to the internet. To fix this problem: reload ". "the page, and then resubmit it. All data inserted to the form will ". "be lost in some browsers so copy them somewhere before reloading.\n\n". $more_info); } return true; } final public function isFormPost() { $post = $this->getExists(self::TYPE_FORM) && $this->isHTTPPost(); if (!$post) { return false; } return $this->validateCSRF(); } final public function getCookie($name, $default = null) { return idx($_COOKIE, $name, $default); } final public function clearCookie($name) { $this->setCookie($name, '', time() - (60 * 60 * 24 * 30)); } final public function setCookie($name, $value, $expire = null) { $is_secure = false; // If a base URI has been configured, ensure cookies are only set on that // domain. Also, use the URI protocol to control SSL-only cookies. $base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri'); if ($base_uri) { $base_uri = new PhutilURI($base_uri); $base_domain = $base_uri->getDomain(); $base_protocol = $base_uri->getProtocol(); $host = $this->getHost(); if ($base_domain != $host) { throw new Exception( "This install of Phabricator is configured as '{$base_domain}' but ". "you are accessing it via '{$host}'. Access Phabricator via ". "the primary configured domain."); } $is_secure = ($base_protocol == 'https'); } else { $base_uri = new PhutilURI(PhabricatorEnv::getRequestBaseURI()); $base_domain = $base_uri->getDomain(); } if ($expire === null) { $expire = time() + (60 * 60 * 24 * 365 * 5); } setcookie( $name, $value, $expire, $path = '/', $base_domain, $is_secure, $http_only = true); return $this; } final public function setUser($user) { $this->user = $user; return $this; } final public function getUser() { return $this->user; } final public function getRequestURI() { $get = $_GET; unset($get['__path__']); $path = phutil_escape_uri($this->getPath()); return id(new PhutilURI($path))->setQueryParams($get); } final public function isDialogFormPost() { return $this->isFormPost() && $this->getStr('__dialog__'); } final public function getRemoteAddr() { return $_SERVER['REMOTE_ADDR']; } public function isHTTPS() { if (empty($_SERVER['HTTPS'])) { return false; } if (!strcasecmp($_SERVER["HTTPS"], "off")) { return false; } return true; } public function isContinueRequest() { return $this->isFormPost() && $this->getStr('__continue__'); } public function isPreviewRequest() { return $this->isFormPost() && $this->getStr('__preview__'); } /** * Get application request parameters in a flattened form suitable for * inclusion in an HTTP request, excluding parameters with special meanings. * This is primarily useful if you want to ask the user for more input and * then resubmit their request. * * @return dict Original request parameters. */ public function getPassthroughRequestParameters() { return self::flattenData($this->getPassthruRequestData()); } /** * Get request data other than "magic" parameters. * * @return dict Request data, with magic filtered out. */ public function getPassthroughRequestData() { $data = $this->getRequestData(); // Remove magic parameters like __dialog__ and __ajax__. foreach ($data as $key => $value) { if (strncmp($key, '__', 2)) { unset($data[$key]); } } return $data; } /** * Flatten an array of key-value pairs (possibly including arrays as values) * into a list of key-value pairs suitable for submitting via HTTP request * (with arrays flattened). * * @param dict Data to flatten. * @return dict Flat data suitable for inclusion in an HTTP * request. */ public static function flattenData(array $data) { $result = array(); foreach ($data as $key => $value) { if (is_array($value)) { foreach (self::flattenData($value) as $fkey => $fvalue) { $fkey = '['.preg_replace('/(?=\[)|$/', ']', $fkey, $limit = 1); $result[$key.$fkey] = $fvalue; } } else { $result[$key] = (string)$value; } } ksort($result); return $result; } } diff --git a/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php index 764df9f14..c50f27867 100644 --- a/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php +++ b/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php @@ -1,387 +1,387 @@ getResourceURIMapRules() + array( '/(?:(?P(?:jump))/)?' => 'PhabricatorDirectoryMainController', '/typeahead/' => array( 'common/(?P\w+)/' => 'PhabricatorTypeaheadCommonDatasourceController', ), '/login/' => array( '' => 'PhabricatorLoginController', 'email/' => 'PhabricatorEmailLoginController', 'etoken/(?P\w+)/' => 'PhabricatorEmailTokenController', 'refresh/' => 'PhabricatorRefreshCSRFController', 'validate/' => 'PhabricatorLoginValidateController', 'mustverify/' => 'PhabricatorMustVerifyEmailController', ), '/logout/' => 'PhabricatorLogoutController', '/oauth/' => array( '(?P\w+)/' => array( 'login/' => 'PhabricatorOAuthLoginController', 'diagnose/' => 'PhabricatorOAuthDiagnosticsController', 'unlink/' => 'PhabricatorOAuthUnlinkController', ), ), '/ldap/' => array( 'login/' => 'PhabricatorLDAPLoginController', 'unlink/' => 'PhabricatorLDAPUnlinkController', ), '/oauthserver/' => array( 'auth/' => 'PhabricatorOAuthServerAuthController', 'test/' => 'PhabricatorOAuthServerTestController', 'token/' => 'PhabricatorOAuthServerTokenController', 'clientauthorization/' => array( '' => 'PhabricatorOAuthClientAuthorizationListController', 'delete/(?P[^/]+)/' => 'PhabricatorOAuthClientAuthorizationDeleteController', 'edit/(?P[^/]+)/' => 'PhabricatorOAuthClientAuthorizationEditController', ), 'client/' => array( '' => 'PhabricatorOAuthClientListController', 'create/' => 'PhabricatorOAuthClientEditController', 'delete/(?P[^/]+)/' => 'PhabricatorOAuthClientDeleteController', 'edit/(?P[^/]+)/' => 'PhabricatorOAuthClientEditController', 'view/(?P[^/]+)/' => 'PhabricatorOAuthClientViewController', ), ), '/xhprof/' => array( 'list/(?P[^/]+)/' => 'PhabricatorXHProfSampleListController', 'profile/(?P[^/]+)/' => 'PhabricatorXHProfProfileController', ), '/~/' => array( '' => 'DarkConsoleController', 'data/(?P[^/]+)/' => 'DarkConsoleDataController', ), '/search/' => array( '' => 'PhabricatorSearchController', '(?P[^/]+)/' => 'PhabricatorSearchController', 'attach/(?P[^/]+)/(?P\w+)/(?:(?P\w+)/)?' => 'PhabricatorSearchAttachController', 'select/(?P\w+)/' => 'PhabricatorSearchSelectController', 'index/(?P[^/]+)/' => 'PhabricatorSearchIndexController', ), '/status/' => 'PhabricatorStatusController', '/help/' => array( 'keyboardshortcut/' => 'PhabricatorHelpKeyboardShortcutController', ), '/chatlog/' => array( '' => 'PhabricatorChatLogChannelListController', 'channel/(?P[^/]+)/' => 'PhabricatorChatLogChannelLogController', ), '/notification/' => array( '(?:(?Pall|unread)/)?' => 'PhabricatorNotificationListController', 'panel/' => 'PhabricatorNotificationPanelController', 'individual/' => 'PhabricatorNotificationIndividualController', 'status/' => 'PhabricatorNotificationStatusController', 'clear/' => 'PhabricatorNotificationClearController', ), '/phortune/' => array( 'stripe/' => array( 'testpaymentform/' => 'PhortuneStripeTestPaymentFormController', ), ), ); } protected function getResourceURIMapRules() { return array( '/res/' => array( '(?Ppkg/)?'. '(?P[a-f0-9]{8})/'. '(?P.+\.(?:css|js|jpg|png|swf|gif))' => 'CelerityPhabricatorResourceController', ), ); } public function buildRequest() { $request = new AphrontRequest($this->getHost(), $this->getPath()); $request->setRequestData($_GET + $_POST); $request->setApplicationConfiguration($this); return $request; } public function handleException(Exception $ex) { $request = $this->getRequest(); // For Conduit requests, return a Conduit response. if ($request->isConduit()) { $response = new ConduitAPIResponse(); $response->setErrorCode(get_class($ex)); $response->setErrorInfo($ex->getMessage()); return id(new AphrontJSONResponse()) ->setContent($response->toDictionary()); } // For non-workflow requests, return a Ajax response. if ($request->isAjax() && !$request->isJavelinWorkflow()) { $response = new AphrontAjaxResponse(); $response->setError( array( 'code' => get_class($ex), 'info' => $ex->getMessage(), )); return $response; } $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); $user = $request->getUser(); if (!$user) { // If we hit an exception very early, we won't have a user. $user = new PhabricatorUser(); } if ($ex instanceof PhabricatorPolicyException) { if (!$user->isLoggedIn()) { // If the user isn't logged in, just give them a login form. This is // probably a generally more useful response than a policy dialog that // they have to click through to get a login form. // // Possibly we should add a header here like "you need to login to see // the thing you are trying to look at". $login_controller = new PhabricatorLoginController($request); return $login_controller->processRequest(); } $content = '
'. phutil_escape_html($ex->getMessage()). '
'; $dialog = new AphrontDialogView(); $dialog ->setTitle( $is_serious ? 'Access Denied' : "You Shall Not Pass") ->setClass('aphront-access-dialog') ->setUser($user) ->appendChild($content); if ($this->getRequest()->isAjax()) { $dialog->addCancelButton('/', 'Close'); } else { $dialog->addCancelButton('/', $is_serious ? 'OK' : 'Away With Thee'); } $response = new AphrontDialogResponse(); $response->setDialog($dialog); return $response; } if ($ex instanceof AphrontUsageException) { $error = new AphrontErrorView(); $error->setTitle(phutil_escape_html($ex->getTitle())); $error->appendChild(phutil_escape_html($ex->getMessage())); $view = new PhabricatorStandardPageView(); $view->setRequest($this->getRequest()); $view->appendChild($error); $response = new AphrontWebpageResponse(); $response->setContent($view->render()); return $response; } // Always log the unhandled exception. phlog($ex); $class = phutil_escape_html(get_class($ex)); $message = phutil_escape_html($ex->getMessage()); if ($ex instanceof AphrontQuerySchemaException) { $message .= "\n\n". "NOTE: This usually indicates that the MySQL schema has not been ". "properly upgraded. Run 'bin/storage upgrade' to ensure your ". "schema is up to date."; } - if (PhabricatorEnv::getEnvConfig('phabricator.show-stack-traces')) { + if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) { $trace = $this->renderStackTrace($ex->getTrace(), $user); } else { $trace = null; } $content = '
'. '
'.$message.'
'. $trace. '
'; $dialog = new AphrontDialogView(); $dialog ->setTitle('Unhandled Exception ("'.$class.'")') ->setClass('aphront-exception-dialog') ->setUser($user) ->appendChild($content); if ($this->getRequest()->isAjax()) { $dialog->addCancelButton('/', 'Close'); } $response = new AphrontDialogResponse(); $response->setDialog($dialog); return $response; } public function willSendResponse(AphrontResponse $response) { return $response; } public function build404Controller() { return array(new Phabricator404Controller($this->getRequest()), array()); } public function buildRedirectController($uri) { return array( new PhabricatorRedirectController($this->getRequest()), array( 'uri' => $uri, )); } private function renderStackTrace($trace, PhabricatorUser $user) { $libraries = PhutilBootloader::getInstance()->getAllLibraries(); // TODO: Make this configurable? $path = 'https://secure.phabricator.com/diffusion/%s/browse/master/src/'; $callsigns = array( 'arcanist' => 'ARC', 'phutil' => 'PHU', 'phabricator' => 'P', ); $rows = array(); $depth = count($trace); foreach ($trace as $part) { $lib = null; $file = idx($part, 'file'); $relative = $file; foreach ($libraries as $library) { $root = phutil_get_library_root($library); if (Filesystem::isDescendant($file, $root)) { $lib = $library; $relative = Filesystem::readablePath($file, $root); break; } } $where = ''; if (isset($part['class'])) { $where .= $part['class'].'::'; } if (isset($part['function'])) { $where .= $part['function'].'()'; } if ($file) { if (isset($callsigns[$lib])) { $attrs = array('title' => $file); try { $attrs['href'] = $user->loadEditorLink( '/src/'.$relative, $part['line'], $callsigns[$lib]); } catch (Exception $ex) { // The database can be inaccessible. } if (empty($attrs['href'])) { $attrs['href'] = sprintf($path, $callsigns[$lib]). str_replace(DIRECTORY_SEPARATOR, '/', $relative). '$'.$part['line']; $attrs['target'] = '_blank'; } $file_name = phutil_tag( 'a', $attrs, $relative); } else { $file_name = phutil_tag( 'span', array( 'title' => $file, ), $relative); } $file_name = $file_name.' : '.(int)$part['line']; } else { $file_name = '(Internal)'; } $rows[] = array( $depth--, phutil_escape_html($lib), $file_name, phutil_escape_html($where), ); } $table = new AphrontTableView($rows); $table->setHeaders( array( 'Depth', 'Library', 'File', 'Where', )); $table->setColumnClasses( array( 'n', '', '', 'wide', )); return '
'. '
Stack Trace
'. $table->render(). '
'; } } diff --git a/src/applications/auth/application/PhabricatorApplicationAuth.php b/src/applications/auth/application/PhabricatorApplicationAuth.php index acd98344e..2bb0926cd 100644 --- a/src/applications/auth/application/PhabricatorApplicationAuth.php +++ b/src/applications/auth/application/PhabricatorApplicationAuth.php @@ -1,33 +1,32 @@ isLoggedIn()) { $item = new PhabricatorMenuItemView(); $item->setName(pht('Log Out')); $item->setIcon('power'); $item->setWorkflow(true); $item->setHref('/logout/'); - $item->setSortOrder(2.0); $item->setSelected(($controller instanceof PhabricatorLogoutController)); $items[] = $item; } return $items; } } diff --git a/src/applications/auth/view/PhabricatorOAuthFailureView.php b/src/applications/auth/view/PhabricatorOAuthFailureView.php index b8fa2afd2..a1e454974 100644 --- a/src/applications/auth/view/PhabricatorOAuthFailureView.php +++ b/src/applications/auth/view/PhabricatorOAuthFailureView.php @@ -1,88 +1,89 @@ request = $request; return $this; } public function setOAuthProvider($provider) { $this->provider = $provider; return $this; } public function setException(Exception $e) { $this->exception = $e; return $this; } public function render() { $request = $this->request; $provider = $this->provider; $provider_name = $provider->getProviderName(); $diagnose = null; $view = new AphrontRequestFailureView(); $view->setHeader(pht('%s Auth Failed', $provider_name)); if ($this->request) { $view->appendChild( hsprintf( '

Description: %s

', $request->getStr('error_description'))); $view->appendChild( hsprintf( '

Error: %s

', $request->getStr('error'))); $view->appendChild( hsprintf( '

Error Reason: %s

', $request->getStr('error_reason'))); } else if ($this->exception) { $view->appendChild( hsprintf( '

Error Details: %s

', $this->exception->getMessage())); } else { // TODO: We can probably refine this. $view->appendChild( hsprintf( '

Unable to authenticate with %s. '. 'There are several reasons this might happen:

'. '
    '. '
  • Phabricator may be configured with the wrong Application '. 'Secret; or
  • '. '
  • the %s OAuth access token may have expired; or
  • '. '
  • %s may have revoked authorization for the Application; '. 'or
  • '. '
  • %s may be having technical problems.
  • '. '
'. '

You can try again, or login using another method.

', $provider_name, $provider_name, $provider_name, $provider_name)); $provider_key = $provider->getProviderKey(); $diagnose = hsprintf( - ''. + ''. 'Diagnose %s OAuth Problems'. '', + $provider_key, $provider_name); } $view->appendChild( '
'. $diagnose. ''.pht('Continue').''. '
'); return $view->render(); } } diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 6bed54389..934b39865 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -1,291 +1,306 @@ pht('Core Applications'), self::GROUP_COMMUNICATION => pht('Communication'), self::GROUP_ORGANIZATION => pht('Organization'), self::GROUP_UTILITIES => pht('Utilities'), self::GROUP_ADMIN => pht('Administration'), self::GROUP_DEVELOPER => pht('Developer Tools'), self::GROUP_MISC => pht('Miscellaneous Applications'), ); } public static function getTileDisplayName($constant) { $names = array( self::TILE_INVISIBLE => pht('Invisible'), self::TILE_HIDE => pht('Hidden'), self::TILE_SHOW => pht('Show Small Tile'), self::TILE_FULL => pht('Show Large Tile'), ); return idx($names, $constant); } /* -( Application Information )-------------------------------------------- */ public function getName() { return substr(get_class($this), strlen('PhabricatorApplication')); } public function getShortDescription() { return $this->getName().' Application'; } public function isEnabled() { return true; } public function isInstalled() { $uninstalled = PhabricatorEnv::getEnvConfig('phabricator.uninstalled-applications'); - if (isset($uninstalled[get_class($this)])) { + if (!$this->canUninstall()) { + return true; + } else if (isset($uninstalled[get_class($this)])) { return false; } else { return true; } } public function isBeta() { return false; } public function canUninstall() { return true; } public function getPHID() { return 'PHID-APPS-'.get_class($this); } public function getTypeaheadURI() { return $this->getBaseURI(); } public function getBaseURI() { return null; } public function getIconURI() { return null; } public function getIconName() { return 'application'; } public function shouldAppearInLaunchView() { return true; } public function getApplicationOrder() { return PHP_INT_MAX; } public function getApplicationGroup() { return self::GROUP_MISC; } public function getTitleGlyph() { return null; } public function getHelpURI() { // TODO: When these applications get created, link to their docs: // // - Drydock // - OAuth Server return null; } public function getEventListeners() { return array(); } public function getDefaultTileDisplay(PhabricatorUser $user) { switch ($this->getApplicationGroup()) { case self::GROUP_CORE: return self::TILE_FULL; case self::GROUP_UTILITIES: case self::GROUP_DEVELOPER: return self::TILE_HIDE; case self::GROUP_ADMIN: if ($user->getIsAdmin()) { return self::TILE_SHOW; } else { return self::TILE_INVISIBLE; } break; default: return self::TILE_SHOW; } } /* -( URI Routing )-------------------------------------------------------- */ public function getRoutes() { return array(); } /* -( Fact Integration )--------------------------------------------------- */ public function getFactObjectsForAnalysis() { return array(); } /* -( UI Integration )----------------------------------------------------- */ /** * Render status elements (like "3 Waiting Reviews") for application list * views. These provide a way to alert users to new or pending action items * in applications. * * @param PhabricatorUser Viewing user. * @return list Application status elements. * @task ui */ public function loadStatus(PhabricatorUser $user) { return array(); } /** * You can provide an optional piece of flavor text for the application. This * is currently rendered in application launch views if the application has no * status elements. * * @return string|null Flavor text. * @task ui */ public function getFlavorText() { return null; } /** * Build items for the main menu. * * @param PhabricatorUser The viewing user. * @param AphrontController The current controller. May be null for special * pages like 404, exception handlers, etc. * @return list List of menu items. * @task ui */ public function buildMainMenuItems( PhabricatorUser $user, PhabricatorController $controller = null) { return array(); } /** * On the Phabricator homepage sidebar, this function returns the URL for * a quick create X link which is displayed in the wide button only. * * @return string * @task ui */ public function getQuickCreateURI() { return null; } /* -( Application Management )--------------------------------------------- */ - public static function getAllApplications() { + public static function getByClass($class_name) { + + $selected = null; + $applications = PhabricatorApplication::getAllApplications(); + + foreach ($applications as $application) { + if (get_class($application) == $class_name) { + $selected = $application; + break; + } + } + return $selected; + } + public static function getAllApplications() { $classes = id(new PhutilSymbolLoader()) ->setAncestorClass(__CLASS__) ->setConcreteOnly(true) ->selectAndLoadSymbols(); $apps = array(); foreach ($classes as $class) { $app = newv($class['name'], array()); $apps[] = $app; } + // Reorder the applications into "application order". Notably, this ensures + // their event handlers register in application order. + $apps = msort($apps, 'getApplicationOrder'); + $apps = mgroup($apps, 'getApplicationGroup'); + $apps = array_select_keys($apps, self::getApplicationGroups()) + $apps; + $apps = array_mergev($apps); + return $apps; } public static function getAllInstalledApplications() { static $applications; $show_beta = PhabricatorEnv::getEnvConfig('phabricator.show-beta-applications'); $uninstalled = PhabricatorEnv::getEnvConfig('phabricator.uninstalled-applications'); - if (empty($applications)) { - $classes = id(new PhutilSymbolLoader()) - ->setAncestorClass(__CLASS__) - ->setConcreteOnly(true) - ->selectAndLoadSymbols(); - + $all_applications = self::getAllApplications(); $apps = array(); - foreach ($classes as $class) { - - if (isset($uninstalled[$class['name']])) { - continue; - } - - $app = newv($class['name'], array()); + foreach ($all_applications as $app) { + $class = get_class($app); + if (isset($uninstalled[$class])) { + continue; + } - if (!$app->isEnabled()) { + if (!$app->isEnabled()) { continue; - } + } - if (!$show_beta && $app->isBeta()) { + if (!$show_beta && $app->isBeta()) { continue; - } + } - $apps[] = $app; + $apps[] = $app; } $applications = $apps; } return $applications; } } diff --git a/src/applications/config/option/PhabricatorDeveloperConfigOptions.php b/src/applications/config/option/PhabricatorDeveloperConfigOptions.php index fba573a60..8f729711e 100644 --- a/src/applications/config/option/PhabricatorDeveloperConfigOptions.php +++ b/src/applications/config/option/PhabricatorDeveloperConfigOptions.php @@ -1,158 +1,128 @@ newOption('darkconsole.enabled', 'bool', false) ->setBoolOptions( array( pht("Enable DarkConsole"), pht("Disable DarkConsole"), )) ->setSummary(pht("Enable Phabricator's debugging console.")) ->setDescription( pht( "DarkConsole is a development and profiling tool built into ". "Phabricator's web interface. You should leave it disabled unless ". "you are developing or debugging Phabricator.\n\n". "Set this option to enable DarkConsole, which will put a link ". "in the page footer to actually activate it. Once activated, ". "it will appear at the top of every page and can be toggled ". "by pressing the '`' key.\n\n". "DarkConsole exposes potentially sensitive data (like queries, ". "stack traces, and configuration) so you generally should not ". "turn it on in production.")), $this->newOption('darkconsole.always-on', 'bool', false) ->setBoolOptions( array( pht("Always Activate DarkConsole"), pht("Require DarkConsole Activation"), )) ->setSummary(pht("Activate DarkConsole on every page.")) ->setDescription( pht( "This option allows you to enable DarkConsole on every page, ". "even for logged-out users. This is only really useful if you ". "need to debug something on a logged-out page. You should not ". "enable this option in production.\n\n". "You must enable DarkConsole by setting {{darkconsole.enabled}} ". "before this option will have any effect.")), $this->newOption('debug.stop-on-redirect', 'bool', false) ->setBoolOptions( array( pht("Stop Before HTTP Redirect"), pht("Use Normal HTTP Redirects"), )) ->setSummary( pht( "Confirm before redirecting so DarkConsole can be examined.")) ->setDescription( pht( "Normally, Phabricator issues HTTP redirects after a successful ". "POST. This can make it difficult to debug things which happen ". "while processing the POST, because service and profiling ". "information are lost. By setting this configuration option, ". "Phabricator will show a page instead of automatically ". "redirecting, allowing you to examine service and profiling ". "information. It also makes the UX awful, so you should only ". "enable it when debugging.")), $this->newOption('debug.profile-rate', 'int', 0) ->addExample(0, pht('No profiling')) ->addExample(1, pht('Profile every request (slow)')) ->addExample(1000, pht('Profile 0.1%% of all requests')) ->setSummary(pht("Automatically profile some percentage of pages.")) ->setDescription( pht( "Normally, Phabricator profiles pages only when explicitly ". "requested via DarkConsole. However, it may be useful to profile ". "some pages automatically.\n\n". "Set this option to a positive integer N to profile 1 / N pages ". "automatically. For example, setting it to 1 will profile every ". "page, while setting it to 1000 will profile 1 page per 1000 ". "requests (i.e., 0.1%% of requests).\n\n". "Since profiling is slow and generates a lot of data, you should ". "set this to 0 in production (to disable it) or to a large number ". "(to collect a few samples, if you're interested in having some ". "data to look at eventually). In development, it may be useful to ". "set it to 1 in order to debug performance problems.\n\n". "NOTE: You must install XHProf for profiling to work.")), - $this->newOption('phabricator.show-stack-traces', 'bool', false) + $this->newOption('phabricator.developer-mode', 'bool', false) ->setBoolOptions( array( - pht('Show stack traces'), - pht('Hide stack traces'), + pht('Enable developer mode'), + pht('Disable developer mode'), )) - ->setSummary(pht("Show stack traces when unhandled exceptions occur.")) - ->setDescription( - pht( - "When unhandled exceptions occur, stack traces are hidden by ". - "default. You can enable traces for development to make it easier ". - "to debug problems.")), - $this->newOption('phabricator.show-error-callout', 'bool', false) - ->setBoolOptions( - array( - pht('Show error callout'), - pht('Hide error callout'), - )) - ->setSummary(pht("Show error callout.")) - ->setDescription( - pht( - "Shows an error callout if a page generated PHP errors, warnings ". - "or notices. This makes it harder to miss problems while ". - "developing Phabricator. A callout is simply a red error at the ". - "top of the page.")), - $this->newOption('celerity.force-disk-reads', 'bool', false) - ->setBoolOptions( - array( - pht('Force disk reads'), - pht("Don't force disk reads"), - )) - ->setSummary(pht("Force Celerity to read from disk on every request.")) - ->setDescription( - pht( - "In a development environment, it is desirable to force static ". - "resources (CSS and JS) to be read from disk on every request, so ". - "that edits to them appear when you reload the page even if you ". - "haven't updated the resource maps. This setting ensures requests ". - "will be verified against the state on disk. Generally, you ". - "should leave this off in production (caching behavior and ". - "performance improve with it off) but turn it on in development. ". - "(These settings are the defaults.)")), + ->setSummary(pht("Enable verbose error reporting and disk reads.")) + ->setDescription( + pht( + "This option enables verbose error reporting (stack traces, ". + "error callouts) and forces disk reads of static assets on ". + "every reload.")), $this->newOption('celerity.minify', 'bool', false) ->setBoolOptions( array( pht('Minify static resources.'), pht("Don't minify static resources."), )) ->setSummary(pht("Minify static Celerity resources.")) ->setDescription( pht( "Minify static resources by removing whitespace and comments. You ". "should enable this in production, but disable it in ". "development.")), $this->newOption('cache.enable-deflate', 'bool', true) ->setBoolOptions( array( pht("Enable deflate compression"), pht("Disable deflate compression"), )) ->setSummary( pht("Toggle gzdeflate()-based compression for some caches.")) ->setDescription( pht( "Set this to false to disable the use of gzdeflate()-based ". "compression in some caches. This may give you less performant ". "(but more debuggable) caching.")), ); } } diff --git a/src/applications/config/response/PhabricatorConfigResponse.php b/src/applications/config/response/PhabricatorConfigResponse.php index 02fc19081..479df39cd 100644 --- a/src/applications/config/response/PhabricatorConfigResponse.php +++ b/src/applications/config/response/PhabricatorConfigResponse.php @@ -1,51 +1,60 @@ view = $view; return $this; } public function buildResponseString() { + // Check to make sure we aren't requesting this via ajax or conduit + if (isset($_REQUEST['__ajax__']) || isset($_REQUEST['__conduit__'])) { + // We don't want to flood the console with html, just return a simple + // message for now. + return pht( + "This install has a fatal setup error, access the internet web ". + "version to view details and resolve it."); + } + $resources = $this->buildResources(); $view = $this->view->render(); $template = << Phabricator Setup {$resources} {$view} EOTEMPLATE; return $template; } private function buildResources() { $css = array( 'application/config/config-template.css', 'application/config/setup-issue.css', ); $webroot = dirname(phutil_get_library_root('phabricator')).'/webroot/'; $resources = array(); foreach ($css as $path) { $resources[] = ''; } return implode("\n", $resources); } } diff --git a/src/applications/conpherence/controller/ConpherenceUpdateController.php b/src/applications/conpherence/controller/ConpherenceUpdateController.php index 69e35a570..2d8deee71 100644 --- a/src/applications/conpherence/controller/ConpherenceUpdateController.php +++ b/src/applications/conpherence/controller/ConpherenceUpdateController.php @@ -1,187 +1,168 @@ conpherenceID = $conpherence_id; return $this; } public function getConpherenceID() { return $this->conpherenceID; } public function willProcessRequest(array $data) { $this->setConpherenceID(idx($data, 'id')); } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $conpherence_id = $this->getConpherenceID(); if (!$conpherence_id) { return new Aphront404Response(); } $conpherence = id(new ConpherenceThreadQuery()) ->setViewer($user) ->withIDs(array($conpherence_id)) ->executeOne(); $supported_formats = PhabricatorFile::getTransformableImageFormats(); $updated = false; $error_view = null; $e_file = array(); $errors = array(); if ($request->isFormPost()) { $content_source = PhabricatorContentSource::newForSource( PhabricatorContentSource::SOURCE_WEB, array( 'ip' => $request->getRemoteAddr() )); $editor = id(new ConpherenceEditor()) + ->setContinueOnNoEffect($request->isContinueRequest()) ->setContentSource($content_source) ->setActor($user); $action = $request->getStr('action'); switch ($action) { case 'message': $message = $request->getStr('text'); $xactions = $editor->generateTransactionsFromText( $conpherence, $message ); - $time = time(); - $conpherence->openTransaction(); - $xactions = $editor->applyTransactions($conpherence, $xactions); - $last_xaction = end($xactions); - $xaction_phid = $last_xaction->getPHID(); - $behind = ConpherenceParticipationStatus::BEHIND; - $up_to_date = ConpherenceParticipationStatus::UP_TO_DATE; - $participants = $conpherence->getParticipants(); - foreach ($participants as $phid => $participant) { - if ($phid != $user->getPHID()) { - if ($participant->getParticipationStatus() != $behind) { - $participant->setBehindTransactionPHID($xaction_phid); - } - $participant->setParticipationStatus($behind); - $participant->setDateTouched($time); - } else { - $participant->setParticipationStatus($up_to_date); - $participant->setDateTouched($time); - } - $participant->save(); - } - $updated = $conpherence->saveTransaction(); break; case 'metadata': $xactions = array(); $images = $request->getArr('image'); if ($images) { // just take the first one $file_phid = reset($images); $file = id(new PhabricatorFileQuery()) ->setViewer($user) ->withPHIDs(array($file_phid)) ->executeOne(); $okay = $file->isTransformableImage(); if ($okay) { $xformer = new PhabricatorImageTransformer(); $xformed = $xformer->executeThumbTransform( $file, $x = 50, $y = 50); $image_phid = $xformed->getPHID(); $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(ConpherenceTransactionType::TYPE_PICTURE) ->setNewValue($image_phid); } else { $e_file[] = $file; $errors[] = pht('This server only supports these image formats: %s.', implode(', ', $supported_formats)); } } $title = $request->getStr('title'); if ($title != $conpherence->getTitle()) { $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(ConpherenceTransactionType::TYPE_TITLE) ->setNewValue($title); } - - if ($xactions) { - $conpherence->openTransaction(); - $xactions = $editor - ->setContinueOnNoEffect(true) - ->applyTransactions($conpherence, $xactions); - $updated = $conpherence->saveTransaction(); - } else if (empty($errors)) { - $errors[] = pht( - 'That was a non-update. Try cancel.' - ); - } break; default: throw new Exception('Unknown action: '.$action); break; } + if ($xactions) { + try { + $xactions = $editor->applyTransactions($conpherence, $xactions); + $updated = true; + } catch (PhabricatorApplicationTransactionNoEffectException $ex) { + return id(new PhabricatorApplicationTransactionNoEffectResponse()) + ->setCancelURI($this->getApplicationURI($conpherence_id.'/')) + ->setException($ex); + } + } else if (empty($errors)) { + $errors[] = pht( + 'That was a non-update. Try cancel.' + ); + } } if ($updated) { return id(new AphrontRedirectResponse())->setURI( $this->getApplicationURI($conpherence_id.'/') ); } if ($errors) { $error_view = id(new AphrontErrorView()) ->setTitle(pht('Errors editing conpherence.')) ->setInsideDialogue(true) ->setErrors($errors); } $form = id(new AphrontFormLayoutView()) ->appendChild( id(new AphrontFormTextControl()) ->setLabel(pht('Title')) ->setName('title') ->setValue($conpherence->getTitle()) ) ->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Image')) ->setValue(phutil_tag( 'img', array( 'src' => $conpherence->loadImageURI(), )) ) ) ->appendChild( id(new AphrontFormDragAndDropUploadControl()) ->setLabel(pht('Change Image')) ->setName('image') ->setValue($e_file) ->setCaption('Supported formats: '.implode(', ', $supported_formats)) ); require_celerity_resource('conpherence-update-css'); return id(new AphrontDialogResponse()) ->setDialog( id(new AphrontDialogView()) ->setUser($user) ->setTitle(pht('Update Conpherence')) ->setWidth(AphrontDialogView::WIDTH_FORM) ->setSubmitURI($this->getApplicationURI('update/'.$conpherence_id.'/')) ->addHiddenInput('action', 'metadata') ->appendChild($error_view) ->appendChild($form) ->addSubmitButton() ->addCancelButton($this->getApplicationURI($conpherence->getID().'/')) ); } } diff --git a/src/applications/conpherence/controller/ConpherenceViewController.php b/src/applications/conpherence/controller/ConpherenceViewController.php index 751079b31..742df9725 100644 --- a/src/applications/conpherence/controller/ConpherenceViewController.php +++ b/src/applications/conpherence/controller/ConpherenceViewController.php @@ -1,299 +1,300 @@ conpherence = $conpherence; return $this; } public function getConpherence() { return $this->conpherence; } public function setConpherenceID($conpherence_id) { $this->conpherenceID = $conpherence_id; return $this; } public function getConpherenceID() { return $this->conpherenceID; } public function willProcessRequest(array $data) { $this->setConpherenceID(idx($data, 'id')); } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $conpherence_id = $this->getConpherenceID(); if (!$conpherence_id) { return new Aphront404Response(); } if (!$request->isAjax()) { return id(new AphrontRedirectResponse()) ->setURI($this->getApplicationURI($conpherence_id.'/')); } $conpherence = id(new ConpherenceThreadQuery()) ->setViewer($user) ->withIDs(array($conpherence_id)) ->needWidgetData(true) ->executeOne(); $this->setConpherence($conpherence); $participant = $conpherence->getParticipant($user->getPHID()); $transactions = $conpherence->getTransactions(); $latest_transaction = end($transactions); $write_guard = AphrontWriteGuard::beginScopedUnguardedWrites(); $participant->markUpToDate($latest_transaction); unset($write_guard); $header = $this->renderHeaderPaneContent(); $messages = $this->renderMessagePaneContent(); $widgets = $this->renderWidgetPaneContent(); $content = $header + $widgets + $messages; return id(new AphrontAjaxResponse())->setContent($content); } private function renderHeaderPaneContent() { require_celerity_resource('conpherence-header-pane-css'); $user = $this->getRequest()->getUser(); $conpherence = $this->getConpherence(); $display_data = $conpherence->getDisplayData($user); $edit_href = $this->getApplicationURI('update/'.$conpherence->getID().'/'); $header = javelin_render_tag( 'a', array( 'class' => 'edit', 'href' => $edit_href, 'sigil' => 'workflow', ), '' ). phutil_render_tag( 'div', array( 'class' => 'header-image', 'style' => 'background-image: url('.$display_data['image'].');' ), '' ). phutil_render_tag( 'div', array( 'class' => 'title', ), phutil_escape_html($display_data['title']) ). phutil_render_tag( 'div', array( 'class' => 'subtitle', ), phutil_escape_html($display_data['subtitle']) ); return array('header' => $header); } private function renderMessagePaneContent() { require_celerity_resource('conpherence-message-pane-css'); $user = $this->getRequest()->getUser(); $conpherence = $this->getConpherence(); $handles = $conpherence->getHandles(); $rendered_transactions = array(); $transactions = $conpherence->getTransactions(); foreach ($transactions as $transaction) { if ($transaction->shouldHide()) { continue; } $rendered_transactions[] = id(new ConpherenceTransactionView()) ->setUser($user) ->setConpherenceTransaction($transaction) ->setHandles($handles) ->render(); } $transactions = implode(' ', $rendered_transactions); $form = id(new AphrontFormView()) + ->setWorkflow(true) ->setAction($this->getApplicationURI('update/'.$conpherence->getID().'/')) ->setFlexible(true) ->setUser($user) ->addHiddenInput('action', 'message') ->appendChild( id(new PhabricatorRemarkupControl()) ->setUser($user) ->setName('text') ) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Pontificate')) )->render(); return array( 'messages' => $transactions, 'form' => $form ); } private function renderWidgetPaneContent() { require_celerity_resource('conpherence-widget-pane-css'); Javelin::initBehavior( 'conpherence-widget-pane', array( 'widgetRegistery' => array( 'widgets-files' => 1, 'widgets-tasks' => 1, 'widgets-calendar' => 1, ) ) ); $conpherence = $this->getConpherence(); $widgets = phutil_render_tag( 'div', array( 'class' => 'widgets-header' ), array( javelin_tag( 'a', array( 'sigil' => 'conpherence-change-widget', 'meta' => array('widget' => 'widgets-files') ), pht('Files') ), ' | ', javelin_tag( 'a', array( 'sigil' => 'conpherence-change-widget', 'meta' => array('widget' => 'widgets-tasks') ), pht('Tasks') ), ' | ', javelin_tag( 'a', array( 'sigil' => 'conpherence-change-widget', 'meta' => array('widget' => 'widgets-calendar') ), pht('Calendar') ), ) ). phutil_render_tag( 'div', array( 'class' => 'widgets-body', 'id' => 'widgets-files', 'style' => 'display: none;' ), $this->renderFilesWidgetPaneContent() ). phutil_render_tag( 'div', array( 'class' => 'widgets-body', 'id' => 'widgets-tasks', ), $this->renderTaskWidgetPaneContent() ). phutil_render_tag( 'div', array( 'class' => 'widgets-body', 'id' => 'widgets-calendar', 'style' => 'display: none;' ), $this->renderCalendarWidgetPaneContent() ); return array('widgets' => $widgets); } private function renderFilesWidgetPaneContent() { $conpherence = $this->getConpherence(); $widget_data = $conpherence->getWidgetData(); $files = $widget_data['files']; $table_data = array(); foreach ($files as $file) { $thumb = $file->getThumb60x45URI(); $table_data[] = array( phutil_tag( 'img', array( 'src' => $thumb ), ''), phutil_escape_html($file->getName()), ); } $header = id(new PhabricatorHeaderView()) ->setHeader(pht('Attached Files')); $table = id(new AphrontTableView($table_data)) ->setNoDataString(pht('No files attached to conpherence.')) ->setHeaders(array('', pht('Name'))) ->setColumnClasses(array('', 'wide')); return $header->render() . $table->render(); } private function renderTaskWidgetPaneContent() { $conpherence = $this->getConpherence(); $widget_data = $conpherence->getWidgetData(); $tasks = $widget_data['tasks']; $priority_map = ManiphestTaskPriority::getTaskPriorityMap(); $handles = $conpherence->getHandles(); $content = array(); foreach ($tasks as $owner_phid => $actual_tasks) { $handle = $handles[$owner_phid]; $content[] = id(new PhabricatorHeaderView()) ->setHeader($handle->getName()) ->render(); $actual_tasks = msort($actual_tasks, 'getPriority'); $actual_tasks = array_reverse($actual_tasks); $data = array(); foreach ($actual_tasks as $task) { $data[] = array( idx($priority_map, $task->getPriority(), pht('???')), phutil_tag( 'a', array( 'href' => '/T'.$task->getID() ), $task->getTitle()), ); } $table = id(new AphrontTableView($data)) ->setNoDataString(pht('No open tasks.')) ->setHeaders(array(pht('Pri'), pht('Title'))) ->setColumnClasses(array('', 'wide')); $content[] = $table->render(); } return implode('', $content); } private function renderCalendarWidgetPaneContent() { $header = id(new PhabricatorHeaderView()) ->setHeader(pht('Calendar')); return $header->render() . 'TODO'; } } diff --git a/src/applications/conpherence/editor/ConpherenceEditor.php b/src/applications/conpherence/editor/ConpherenceEditor.php index 9304e0f14..a5b42b93c 100644 --- a/src/applications/conpherence/editor/ConpherenceEditor.php +++ b/src/applications/conpherence/editor/ConpherenceEditor.php @@ -1,217 +1,238 @@ getFilePHIDs(); $file_phids = array_diff($file_phids, $existing_file_phids); if ($file_phids) { $files = id(new PhabricatorFileQuery()) ->setViewer($this->getActor()) ->withPHIDs($file_phids) ->execute(); } $xactions = array(); if ($files) { $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(ConpherenceTransactionType::TYPE_FILES) ->setNewValue(array('+' => mpull($files, 'getPHID'))); } $xactions[] = id(new ConpherenceTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) ->attachComment( id(new ConpherenceTransactionComment()) ->setContent($text) ->setConpherencePHID($conpherence->getPHID()) ); return $xactions; } public function getTransactionTypes() { $types = parent::getTransactionTypes(); $types[] = PhabricatorTransactions::TYPE_COMMENT; $types[] = ConpherenceTransactionType::TYPE_TITLE; $types[] = ConpherenceTransactionType::TYPE_PICTURE; $types[] = ConpherenceTransactionType::TYPE_PARTICIPANTS; $types[] = ConpherenceTransactionType::TYPE_FILES; return $types; } protected function getCustomTransactionOldValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case ConpherenceTransactionType::TYPE_TITLE: return $object->getTitle(); case ConpherenceTransactionType::TYPE_PICTURE: return $object->getImagePHID(); case ConpherenceTransactionType::TYPE_PARTICIPANTS: return $object->getParticipantPHIDs(); case ConpherenceTransactionType::TYPE_FILES: return $object->getFilePHIDs(); } } protected function getCustomTransactionNewValue( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case ConpherenceTransactionType::TYPE_TITLE: case ConpherenceTransactionType::TYPE_PICTURE: return $xaction->getNewValue(); case ConpherenceTransactionType::TYPE_PARTICIPANTS: case ConpherenceTransactionType::TYPE_FILES: return $this->getPHIDTransactionNewValue($xaction); } } protected function applyCustomInternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case ConpherenceTransactionType::TYPE_TITLE: $object->setTitle($xaction->getNewValue()); break; case ConpherenceTransactionType::TYPE_PICTURE: $object->setImagePHID($xaction->getNewValue()); break; } } /** * For now this only supports adding more files and participants. */ protected function applyCustomExternalTransaction( PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction) { switch ($xaction->getTransactionType()) { case ConpherenceTransactionType::TYPE_FILES: $editor = id(new PhabricatorEdgeEditor()) ->setActor($this->getActor()); $edge_type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_FILE; foreach ($xaction->getNewValue() as $file_phid) { $editor->addEdge( $object->getPHID(), $edge_type, $file_phid ); } $editor->save(); + // fallthrough + case PhabricatorTransactions::TYPE_COMMENT: + $xaction_phid = $xaction->getPHID(); + $behind = ConpherenceParticipationStatus::BEHIND; + $up_to_date = ConpherenceParticipationStatus::UP_TO_DATE; + $participants = $object->getParticipants(); + $user = $this->getActor(); + $time = time(); + foreach ($participants as $phid => $participant) { + if ($phid != $user->getPHID()) { + if ($participant->getParticipationStatus() != $behind) { + $participant->setBehindTransactionPHID($xaction_phid); + } + $participant->setParticipationStatus($behind); + $participant->setDateTouched($time); + } else { + $participant->setParticipationStatus($up_to_date); + $participant->setDateTouched($time); + } + $participant->save(); + } break; case ConpherenceTransactionType::TYPE_PARTICIPANTS: foreach ($xaction->getNewValue() as $participant) { if ($participant == $this->getActor()->getPHID()) { $status = ConpherenceParticipationStatus::UP_TO_DATE; } else { $status = ConpherenceParticipationStatus::BEHIND; } id(new ConpherenceParticipant()) ->setConpherencePHID($object->getPHID()) ->setParticipantPHID($participant) ->setParticipationStatus($status) ->setDateTouched(time()) ->setBehindTransactionPHID($xaction->getPHID()) ->save(); } break; } } protected function mergeTransactions( PhabricatorApplicationTransaction $u, PhabricatorApplicationTransaction $v) { $type = $u->getTransactionType(); switch ($type) { case ConpherenceTransactionType::TYPE_TITLE: case ConpherenceTransactionType::TYPE_PICTURE: return $v; case ConpherenceTransactionType::TYPE_FILES: case ConpherenceTransactionType::TYPE_PARTICIPANTS: return $this->mergePHIDTransactions($u, $v); } return parent::mergeTransactions($u, $v); } protected function supportsMail() { return true; } protected function buildReplyHandler(PhabricatorLiskDAO $object) { return id(new ConpherenceReplyHandler()) ->setActor($this->getActor()) ->setMailReceiver($object); } protected function buildMailTemplate(PhabricatorLiskDAO $object) { $id = $object->getID(); $title = $object->getTitle(); if (!$title) { $title = pht( '%s sent you a message.', $this->getActor()->getUserName() ); } $phid = $object->getPHID(); return id(new PhabricatorMetaMTAMail()) ->setSubject("E{$id}: {$title}") ->addHeader('Thread-Topic', "E{$id}: {$phid}"); } protected function getMailTo(PhabricatorLiskDAO $object) { $participants = $object->getParticipants(); return array_keys($participants); } protected function getMailCC(PhabricatorLiskDAO $object) { return array(); } protected function buildMailBody( PhabricatorLiskDAO $object, array $xactions) { $body = parent::buildMailBody($object, $xactions); $body->addTextSection( pht('CONPHERENCE DETAIL'), PhabricatorEnv::getProductionURI('/conpherence/'.$object->getID().'/')); return $body; } protected function getMailSubjectPrefix() { return PhabricatorEnv::getEnvConfig('metamta.conpherence.subject-prefix'); } protected function supportsFeed() { return false; } protected function supportsSearch() { return false; } } diff --git a/src/applications/differential/controller/DifferentialRevisionListController.php b/src/applications/differential/controller/DifferentialRevisionListController.php index 59188c7d0..2d670623e 100644 --- a/src/applications/differential/controller/DifferentialRevisionListController.php +++ b/src/applications/differential/controller/DifferentialRevisionListController.php @@ -1,517 +1,517 @@ allowsAnonymousAccess(); } public function willProcessRequest(array $data) { $this->filter = idx($data, 'filter'); $this->username = idx($data, 'username'); } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $viewer_is_anonymous = !$user->isLoggedIn(); $params = array_filter( array( 'status' => $request->getStr('status'), 'order' => $request->getStr('order'), )); $params['participants'] = $request->getArr('participants'); $default_filter = ($viewer_is_anonymous ? 'all' : 'active'); $filters = $this->getFilters(); $this->filter = $this->selectFilter( $filters, $this->filter, $default_filter); // Redirect from search to canonical URL. $phid_arr = $request->getArr('view_users'); if ($phid_arr) { $view_users = id(new PhabricatorUser()) ->loadAllWhere('phid IN (%Ls)', $phid_arr); if (count($view_users) == 1) { // This is a single user, so generate a pretty URI. $uri = new PhutilURI( '/differential/filter/'.$this->filter.'/'. phutil_escape_uri(reset($view_users)->getUserName()).'/'); $uri->setQueryParams($params); return id(new AphrontRedirectResponse())->setURI($uri); } } $uri = new PhutilURI('/differential/filter/'.$this->filter.'/'); $uri->setQueryParams($params); $username = ''; if ($this->username) { $view_user = id(new PhabricatorUser()) ->loadOneWhere('userName = %s', $this->username); if (!$view_user) { return new Aphront404Response(); } $username = phutil_escape_uri($this->username).'/'; $uri->setPath('/differential/filter/'.$this->filter.'/'.$username); $params['view_users'] = array($view_user->getPHID()); } else { $phids = $request->getArr('view_users'); if ($phids) { $params['view_users'] = $phids; $uri->setQueryParams($params); } } // Fill in the defaults we'll actually use for calculations if any // parameters are missing. $params += array( 'view_users' => array($user->getPHID()), 'status' => 'all', 'order' => 'modified', ); $side_nav = new AphrontSideNavFilterView(); $side_nav->setBaseURI(id(clone $uri)->setPath('/differential/filter/')); foreach ($filters as $filter) { list($filter_name, $display_name) = $filter; if ($filter_name) { $side_nav->addFilter($filter_name.'/'.$username, $display_name); } else { $side_nav->addLabel($display_name); } } $side_nav->selectFilter($this->filter.'/'.$username, null); $panels = array(); $handles = array(); $controls = $this->getFilterControls($this->filter); if ($this->getFilterRequiresUser($this->filter) && !$params['view_users']) { // In the anonymous case, we still want to let you see some user's // list, but we don't have a default PHID to provide (normally, we use // the viewing user's). Show a warning instead. $warning = new AphrontErrorView(); $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING); $warning->setTitle(pht('User Required')); $warning->appendChild( pht('This filter requires that a user be specified above.')); $panels[] = $warning; } else { $query = $this->buildQuery($this->filter, $params); $pager = null; if ($this->getFilterAllowsPaging($this->filter)) { $pager = new AphrontPagerView(); $pager->setOffset($request->getInt('page')); $pager->setPageSize(1000); $pager->setURI($uri, 'page'); $query->setOffset($pager->getOffset()); $query->setLimit($pager->getPageSize() + 1); } foreach ($controls as $control) { $this->applyControlToQuery($control, $query, $params); } $revisions = $query->execute(); if ($pager) { $revisions = $pager->sliceResults($revisions); } $views = $this->buildViews( $this->filter, $params['view_users'], $revisions); $view_objects = array(); foreach ($views as $view) { if (empty($view['special'])) { $view_objects[] = $view['view']; } } $phids = mpull($view_objects, 'getRequiredHandlePHIDs'); $phids[] = $params['view_users']; $phids = array_mergev($phids); $handles = $this->loadViewerHandles($phids); foreach ($views as $view) { if (empty($view['special'])) { $view['view']->setHandles($handles); } $panel = new AphrontPanelView(); $panel->setHeader($view['title']); $panel->appendChild($view['view']); if ($pager) { $panel->appendChild($pager); } $panel->setNoBackground(); $panels[] = $panel; } } $filter_form = id(new AphrontFormView()) ->setMethod('GET') ->setAction('/differential/filter/'.$this->filter.'/') ->setUser($user); foreach ($controls as $control) { $control_view = $this->renderControl($control, $handles, $uri, $params); $filter_form->appendChild($control_view); } $filter_form ->addHiddenInput('status', $params['status']) ->addHiddenInput('order', $params['order']) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Filter Revisions'))); $filter_view = new AphrontListFilterView(); $filter_view->appendChild($filter_form); $side_nav->appendChild($filter_view); foreach ($panels as $panel) { $side_nav->appendChild($panel); } $crumbs = $this->buildApplicationCrumbs(); $name = $side_nav ->getMenu() ->getItem($side_nav->getSelectedFilter()) ->getName(); $crumbs->addCrumb( id(new PhabricatorCrumbView()) ->setName($name) ->setHref($request->getRequestURI())); $side_nav->setCrumbs($crumbs); return $this->buildApplicationPage( $side_nav, array( 'title' => pht('Differential Home'), )); } private function getFilters() { return array( array(null, pht('User Revisions')), array('active', pht('Active')), array('revisions', pht('Revisions')), array('reviews', pht('Reviews')), array('subscribed', pht('Subscribed')), array('drafts', pht('Draft Reviews')), array(null, pht('All Revisions')), array('all', pht('All')), ); } private function selectFilter( array $filters, $requested_filter, $default_filter) { // If the user requested a filter, make sure it actually exists. if ($requested_filter) { foreach ($filters as $filter) { if ($filter[0] === $requested_filter) { return $requested_filter; } } } // If not, return the default filter. return $default_filter; } private function getFilterRequiresUser($filter) { static $requires = array( 'active' => true, 'revisions' => true, 'reviews' => true, 'subscribed' => true, 'drafts' => true, 'all' => false, ); if (!isset($requires[$filter])) { throw new Exception("Unknown filter '{$filter}'!"); } return $requires[$filter]; } private function getFilterAllowsPaging($filter) { static $allows = array( 'active' => false, 'revisions' => true, 'reviews' => true, 'subscribed' => true, 'drafts' => true, 'all' => true, ); if (!isset($allows[$filter])) { throw new Exception("Unknown filter '{$filter}'!"); } return $allows[$filter]; } private function getFilterControls($filter) { static $controls = array( 'active' => array('phid'), 'revisions' => array('phid', 'participants', 'status', 'order'), 'reviews' => array('phid', 'participants', 'status', 'order'), 'subscribed' => array('subscriber', 'status', 'order'), 'drafts' => array('phid', 'status', 'order'), 'all' => array('status', 'order'), ); if (!isset($controls[$filter])) { throw new Exception("Unknown filter '{$filter}'!"); } return $controls[$filter]; } private function buildQuery($filter, array $params) { $user_phids = $params['view_users']; $query = new DifferentialRevisionQuery(); $query->needRelationships(true); switch ($filter) { case 'active': $query->withResponsibleUsers($user_phids); $query->withStatus(DifferentialRevisionQuery::STATUS_OPEN); $query->setLimit(null); break; case 'revisions': $query->withAuthors($user_phids); $query->withReviewers($params['participants']); break; case 'reviews': $query->withReviewers($user_phids); $query->withAuthors($params['participants']); break; case 'subscribed': $query->withSubscribers($user_phids); break; case 'drafts': $query->withDraftRepliesByAuthors($user_phids); break; case 'all': break; default: throw new Exception("Unknown filter '{$filter}'!"); } return $query; } private function renderControl( $control, array $handles, PhutilURI $uri, array $params) { assert_instances_of($handles, 'PhabricatorObjectHandle'); switch ($control) { case 'subscriber': case 'phid': $value = mpull( array_select_keys($handles, $params['view_users']), 'getFullName'); if ($control == 'subscriber') { $source = '/typeahead/common/allmailable/'; $label = pht('View Subscribers'); } else { $source = '/typeahead/common/accounts/'; switch ($this->filter) { case 'revisions': $label = pht('Authors'); break; case 'reviews': $label = pht('Reviewers'); break; default: $label = pht('View Users'); break; } } return id(new AphrontFormTokenizerControl()) ->setDatasource($source) ->setLabel($label) ->setName('view_users') ->setValue($value); case 'participants': switch ($this->filter) { case 'revisions': $label = pht('Reviewers'); break; case 'reviews': $label = pht('Authors'); break; } $value = mpull( array_select_keys($handles, $params['participants']), 'getFullName'); return id(new AphrontFormTokenizerControl()) - ->setDatasource('/typeahead/common/allmailable/') + ->setDatasource('/typeahead/common/accounts/') ->setLabel($label) ->setName('participants') ->setValue($value); case 'status': return id(new AphrontFormToggleButtonsControl()) ->setLabel(pht('Status')) ->setValue($params['status']) ->setBaseURI($uri, 'status') ->setButtons( array( 'all' => pht('All'), 'open' => pht('Open'), 'closed' => pht('Closed'), 'abandoned' => pht('Abandoned'), )); case 'order': return id(new AphrontFormToggleButtonsControl()) ->setLabel(pht('Order')) ->setValue($params['order']) ->setBaseURI($uri, 'order') ->setButtons( array( 'modified' => pht('Updated'), 'created' => pht('Created'), )); default: throw new Exception("Unknown control '{$control}'!"); } } private function applyControlToQuery($control, $query, array $params) { switch ($control) { case 'phid': case 'subscriber': case 'participants': // Already applied by query construction. break; case 'status': if ($params['status'] == 'open') { $query->withStatus(DifferentialRevisionQuery::STATUS_OPEN); } else if ($params['status'] == 'closed') { $query->withStatus(DifferentialRevisionQuery::STATUS_CLOSED); } else if ($params['status'] == 'abandoned') { $query->withStatus(DifferentialRevisionQuery::STATUS_ABANDONED); } break; case 'order': if ($params['order'] == 'created') { $query->setOrder(DifferentialRevisionQuery::ORDER_CREATED); } break; default: throw new Exception("Unknown control '{$control}'!"); } } private function buildViews($filter, array $user_phids, array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); $user = $this->getRequest()->getUser(); $template = id(new DifferentialRevisionListView()) ->setUser($user) ->setFields(DifferentialRevisionListView::getDefaultFields()); $views = array(); switch ($filter) { case 'active': list($blocking, $active, $waiting) = DifferentialRevisionQuery::splitResponsible( $revisions, $user_phids); $view = id(clone $template) ->setHighlightAge(true) ->setRevisions($blocking) ->loadAssets(); $views[] = array( 'title' => pht('Blocking Others'), 'view' => $view, ); $view = id(clone $template) ->setHighlightAge(true) ->setRevisions($active) ->loadAssets(); $views[] = array( 'title' => pht('Action Required'), 'view' => $view, ); // Flags are sort of private, so only show the flag panel if you're // looking at your own requests. if (in_array($user->getPHID(), $user_phids)) { $flags = id(new PhabricatorFlagQuery()) ->withOwnerPHIDs(array($user->getPHID())) ->withTypes(array(PhabricatorPHIDConstants::PHID_TYPE_DREV)) ->needHandles(true) ->execute(); if ($flags) { $view = id(new PhabricatorFlagListView()) ->setFlags($flags) ->setUser($user); $views[] = array( 'title' => pht('Flagged Revisions'), 'view' => $view, 'special' => true, ); } } $view = id(clone $template) ->setRevisions($waiting) ->loadAssets(); $views[] = array( 'title' => pht('Waiting On Others'), 'view' => $view, ); break; case 'revisions': case 'reviews': case 'subscribed': case 'drafts': case 'all': $titles = array( 'revisions' => pht('Revisions by Author'), 'reviews' => pht('Revisions by Reviewer'), 'subscribed' => pht('Revisions by Subscriber'), 'all' => pht('Revisions'), ); $view = id(clone $template) ->setRevisions($revisions) ->loadAssets(); $views[] = array( 'title' => idx($titles, $filter), 'view' => $view, ); break; default: throw new Exception("Unknown filter '{$filter}'!"); } return $views; } } diff --git a/src/applications/differential/controller/DifferentialRevisionViewController.php b/src/applications/differential/controller/DifferentialRevisionViewController.php index 3096cfaeb..c48883d6e 100644 --- a/src/applications/differential/controller/DifferentialRevisionViewController.php +++ b/src/applications/differential/controller/DifferentialRevisionViewController.php @@ -1,979 +1,977 @@ allowsAnonymousAccess(); } public function willProcessRequest(array $data) { $this->revisionID = $data['id']; } public function processRequest() { $request = $this->getRequest(); $user = $request->getUser(); $viewer_is_anonymous = !$user->isLoggedIn(); $revision = id(new DifferentialRevision())->load($this->revisionID); if (!$revision) { return new Aphront404Response(); } $revision->loadRelationships(); $diffs = $revision->loadDiffs(); if (!$diffs) { throw new Exception( "This revision has no diffs. Something has gone quite wrong."); } $diff_vs = $request->getInt('vs'); $target_id = $request->getInt('id'); $target = idx($diffs, $target_id, end($diffs)); $target_manual = $target; if (!$target_id) { foreach ($diffs as $diff) { if ($diff->getCreationMethod() != 'commit') { $target_manual = $diff; } } } if (empty($diffs[$diff_vs])) { $diff_vs = null; } $arc_project = $target->loadArcanistProject(); $repository = ($arc_project ? $arc_project->loadRepository() : null); list($changesets, $vs_map, $vs_changesets, $rendering_references) = $this->loadChangesetsAndVsMap( $target, idx($diffs, $diff_vs), $repository); if ($request->getExists('download')) { return $this->buildRawDiffResponse( $changesets, $vs_changesets, $vs_map, $repository); } $props = id(new DifferentialDiffProperty())->loadAllWhere( 'diffID = %d', $target_manual->getID()); $props = mpull($props, 'getData', 'getName'); $aux_fields = $this->loadAuxiliaryFields($revision); $comments = $revision->loadComments(); $comments = array_merge( $this->getImplicitComments($revision, reset($diffs)), $comments); $all_changesets = $changesets; $inlines = $this->loadInlineComments($comments, $all_changesets); $object_phids = array_merge( $revision->getReviewers(), $revision->getCCPHIDs(), $revision->loadCommitPHIDs(), array( $revision->getAuthorPHID(), $user->getPHID(), ), mpull($comments, 'getAuthorPHID')); foreach ($comments as $comment) { $metadata = $comment->getMetadata(); $added_reviewers = idx( $metadata, DifferentialComment::METADATA_ADDED_REVIEWERS); if ($added_reviewers) { foreach ($added_reviewers as $phid) { $object_phids[] = $phid; } } $added_ccs = idx( $metadata, DifferentialComment::METADATA_ADDED_CCS); if ($added_ccs) { foreach ($added_ccs as $phid) { $object_phids[] = $phid; } } } foreach ($revision->getAttached() as $type => $phids) { foreach ($phids as $phid => $info) { $object_phids[] = $phid; } } $aux_phids = array(); foreach ($aux_fields as $key => $aux_field) { $aux_field->setDiff($target); $aux_field->setManualDiff($target_manual); $aux_field->setDiffProperties($props); $aux_phids[$key] = $aux_field->getRequiredHandlePHIDsForRevisionView(); } $object_phids = array_merge($object_phids, array_mergev($aux_phids)); $object_phids = array_unique($object_phids); $handles = $this->loadViewerHandles($object_phids); foreach ($aux_fields as $key => $aux_field) { // Make sure each field only has access to handles it specifically // requested, not all handles. Otherwise you can get a field which works // only in the presence of other fields. $aux_field->setHandles(array_select_keys($handles, $aux_phids[$key])); } $reviewer_warning = null; if ($revision->getStatus() == ArcanistDifferentialRevisionStatus::NEEDS_REVIEW) { $has_live_reviewer = false; foreach ($revision->getReviewers() as $reviewer) { if (!$handles[$reviewer]->isDisabled()) { $has_live_reviewer = true; break; } } if (!$has_live_reviewer) { $reviewer_warning = new AphrontErrorView(); $reviewer_warning->setSeverity(AphrontErrorView::SEVERITY_WARNING); $reviewer_warning->setTitle(pht('No Active Reviewers')); if ($revision->getReviewers()) { $reviewer_warning->appendChild( phutil_tag( 'p', array(), pht('All specified reviewers are disabled and this revision '. 'needs review. You may want to add some new reviewers.') )); } else { $reviewer_warning->appendChild( phutil_tag( 'p', array(), pht('This revision has no specified reviewers and needs '. 'review. You may want to add some reviewers.') )); } } } $request_uri = $request->getRequestURI(); $limit = 100; $large = $request->getStr('large'); if (count($changesets) > $limit && !$large) { $count = count($changesets); $warning = new AphrontErrorView(); $warning->setTitle('Very Large Diff'); $warning->setSeverity(AphrontErrorView::SEVERITY_WARNING); $warning->appendChild( pht( - 'This diff is very large and affects %2$s files. Load each file '. + 'This diff is very large and affects %s files. Load each file '. 'individually.', - $count, - PhutilTranslator::getInstance()->formatNumber($count)). + new PhutilNumber($count)). " ". phutil_tag( 'a', array( 'href' => $request_uri ->alter('large', 'true') ->setFragment('toc'), ), pht('Show All Files Inline')). ""); $warning = $warning->render(); $my_inlines = id(new DifferentialInlineComment())->loadAllWhere( 'revisionID = %d AND commentID IS NULL AND authorPHID = %s AND '. 'changesetID IN (%Ld)', $this->revisionID, $user->getPHID(), mpull($changesets, 'getID')); $visible_changesets = array(); foreach ($inlines + $my_inlines as $inline) { $changeset_id = $inline->getChangesetID(); if (isset($changesets[$changeset_id])) { $visible_changesets[$changeset_id] = $changesets[$changeset_id]; } } if (!empty($props['arc:lint'])) { $changeset_paths = mpull($changesets, null, 'getFilename'); foreach ($props['arc:lint'] as $lint) { $changeset = idx($changeset_paths, $lint['path']); if ($changeset) { $visible_changesets[$changeset->getID()] = $changeset; } } } } else { $warning = null; $visible_changesets = $changesets; } $revision_detail = new DifferentialRevisionDetailView(); $revision_detail->setRevision($revision); $revision_detail->setDiff(reset($diffs)); $revision_detail->setAuxiliaryFields($aux_fields); $actions = $this->getRevisionActions($revision); $custom_renderer_class = PhabricatorEnv::getEnvConfig( 'differential.revision-custom-detail-renderer'); if ($custom_renderer_class) { // TODO: build a better version of the action links and deprecate the // whole DifferentialRevisionDetailRenderer class. $custom_renderer = newv($custom_renderer_class, array()); $custom_renderer->setDiff($target); if ($diff_vs) { $custom_renderer->setVSDiff($diffs[$diff_vs]); } $actions = array_merge( $actions, $custom_renderer->generateActionLinks($revision, $target_manual)); } $whitespace = $request->getStr( 'whitespace', DifferentialChangesetParser::WHITESPACE_IGNORE_ALL); if ($arc_project) { list($symbol_indexes, $project_phids) = $this->buildSymbolIndexes( $arc_project, $visible_changesets); } else { $symbol_indexes = array(); $project_phids = null; } $revision_detail->setActions($actions); $revision_detail->setUser($user); $comment_view = new DifferentialRevisionCommentListView(); $comment_view->setComments($comments); $comment_view->setHandles($handles); $comment_view->setInlineComments($inlines); $comment_view->setChangesets($all_changesets); $comment_view->setUser($user); $comment_view->setTargetDiff($target); $comment_view->setVersusDiffID($diff_vs); if ($arc_project) { Javelin::initBehavior( 'repository-crossreference', array( 'section' => $comment_view->getID(), 'projects' => $project_phids, )); } $changeset_view = new DifferentialChangesetListView(); $changeset_view->setChangesets($changesets); $changeset_view->setVisibleChangesets($visible_changesets); if (!$viewer_is_anonymous) { $changeset_view->setInlineCommentControllerURI( '/differential/comment/inline/edit/'.$revision->getID().'/'); } $changeset_view->setStandaloneURI('/differential/changeset/'); $changeset_view->setRawFileURIs( '/differential/changeset/?view=old', '/differential/changeset/?view=new'); $changeset_view->setUser($user); $changeset_view->setDiff($target); $changeset_view->setRenderingReferences($rendering_references); $changeset_view->setVsMap($vs_map); $changeset_view->setWhitespace($whitespace); if ($repository) { $changeset_view->setRepository($repository); } $changeset_view->setSymbolIndexes($symbol_indexes); $changeset_view->setTitle('Diff '.$target->getID()); $diff_history = new DifferentialRevisionUpdateHistoryView(); $diff_history->setDiffs($diffs); $diff_history->setSelectedVersusDiffID($diff_vs); $diff_history->setSelectedDiffID($target->getID()); $diff_history->setSelectedWhitespace($whitespace); $diff_history->setUser($user); $local_view = new DifferentialLocalCommitsView(); $local_view->setUser($user); $local_view->setLocalCommits(idx($props, 'local:commits')); if ($repository) { $other_revisions = $this->loadOtherRevisions( $changesets, $target, $repository); } else { $other_revisions = array(); } $other_view = null; if ($other_revisions) { $other_view = $this->renderOtherRevisions($other_revisions); } $toc_view = new DifferentialDiffTableOfContentsView(); $toc_view->setChangesets($changesets); $toc_view->setVisibleChangesets($visible_changesets); $toc_view->setRenderingReferences($rendering_references); $toc_view->setUnitTestData(idx($props, 'arc:unit', array())); if ($repository) { $toc_view->setRepository($repository); } $toc_view->setDiff($target); $toc_view->setUser($user); $toc_view->setRevisionID($revision->getID()); $toc_view->setWhitespace($whitespace); $comment_form = null; if (!$viewer_is_anonymous) { $draft = id(new PhabricatorDraft())->loadOneWhere( 'authorPHID = %s AND draftKey = %s', $user->getPHID(), 'differential-comment-'.$revision->getID()); $reviewers = array(); $ccs = array(); if ($draft) { $reviewers = idx($draft->getMetadata(), 'reviewers', array()); $ccs = idx($draft->getMetadata(), 'ccs', array()); if ($reviewers || $ccs) { $handles = $this->loadViewerHandles(array_merge($reviewers, $ccs)); $reviewers = array_select_keys($handles, $reviewers); $ccs = array_select_keys($handles, $ccs); } } $comment_form = new DifferentialAddCommentView(); $comment_form->setRevision($revision); $comment_form->setAuxFields($aux_fields); $comment_form->setActions($this->getRevisionCommentActions($revision)); $comment_form->setActionURI('/differential/comment/save/'); $comment_form->setUser($user); $comment_form->setDraft($draft); $comment_form->setReviewers(mpull($reviewers, 'getFullName', 'getPHID')); $comment_form->setCCs(mpull($ccs, 'getFullName', 'getPHID')); } $pane_id = celerity_generate_unique_node_id(); Javelin::initBehavior( 'differential-keyboard-navigation', array( 'haunt' => $pane_id, )); Javelin::initBehavior('differential-user-select'); $page_pane = id(new DifferentialPrimaryPaneView()) ->setID($pane_id) ->appendChild( $comment_view->render(). $diff_history->render(). $warning. $local_view->render(). $toc_view->render(). $other_view. $changeset_view->render()); if ($comment_form) { $page_pane->appendChild($comment_form->render()); } PhabricatorFeedStoryNotification::updateObjectNotificationViews( $user, $revision->getPHID()); $object_id = 'D'.$revision->getID(); $top_anchor = id(new PhabricatorAnchorView()) ->setAnchorName('top') ->setNavigationMarker(true); $nav = id(new DifferentialChangesetFileTreeSideNavBuilder()) ->setAnchorName('top') ->setTitle('D'.$revision->getID()) ->setBaseURI(new PhutilURI('/D'.$revision->getID())) ->build($changesets); $nav->appendChild( array( $reviewer_warning, $top_anchor, $revision_detail, $page_pane, )); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addCrumb( id(new PhabricatorCrumbView()) ->setName($object_id) ->setHref('/'.$object_id)); $nav->setCrumbs($crumbs); return $this->buildApplicationPage( $nav, array( 'title' => $object_id.' '.$revision->getTitle(), )); } private function getImplicitComments( DifferentialRevision $revision, DifferentialDiff $diff) { $author_phid = nonempty( $diff->getAuthorPHID(), $revision->getAuthorPHID()); $template = new DifferentialComment(); $template->setAuthorPHID($author_phid); $template->setRevisionID($revision->getID()); $template->setDateCreated($revision->getDateCreated()); $comments = array(); if (strlen($revision->getSummary())) { $summary_comment = clone $template; $summary_comment->setContent($revision->getSummary()); $summary_comment->setAction(DifferentialAction::ACTION_SUMMARIZE); $comments[] = $summary_comment; } if (strlen($revision->getTestPlan())) { $testplan_comment = clone $template; $testplan_comment->setContent($revision->getTestPlan()); $testplan_comment->setAction(DifferentialAction::ACTION_TESTPLAN); $comments[] = $testplan_comment; } return $comments; } private function getRevisionActions(DifferentialRevision $revision) { $user = $this->getRequest()->getUser(); $viewer_phid = $user->getPHID(); $viewer_is_owner = ($revision->getAuthorPHID() == $viewer_phid); $viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers()); $viewer_is_cc = in_array($viewer_phid, $revision->getCCPHIDs()); $viewer_is_anonymous = !$this->getRequest()->getUser()->isLoggedIn(); $status = $revision->getStatus(); $revision_id = $revision->getID(); $revision_phid = $revision->getPHID(); $links = array(); if ($viewer_is_owner) { $links[] = array( 'icon' => 'edit', 'href' => "/differential/revision/edit/{$revision_id}/", 'name' => pht('Edit Revision'), ); } if (!$viewer_is_anonymous) { if (!$viewer_is_owner && !$viewer_is_reviewer) { $action = $viewer_is_cc ? 'rem' : 'add'; $links[] = array( 'icon' => $viewer_is_cc ? 'subscribe-delete' : 'subscribe-add', 'href' => "/differential/subscribe/{$action}/{$revision_id}/", 'name' => $viewer_is_cc ? pht('Unsubscribe') : pht('Subscribe'), 'instant' => true, - 'sigil' => 'workflow', ); } else { $links[] = array( 'icon' => 'subscribe-auto', 'name' => pht('Automatically Subscribed'), 'disabled' => true, ); } require_celerity_resource('phabricator-object-selector-css'); require_celerity_resource('javelin-behavior-phabricator-object-selector'); $links[] = array( 'icon' => 'link', 'name' => pht('Edit Dependencies'), 'href' => "/search/attach/{$revision_phid}/DREV/dependencies/", 'sigil' => 'workflow', ); if (PhabricatorEnv::getEnvConfig('maniphest.enabled')) { $links[] = array( 'icon' => 'attach', 'name' => pht('Edit Maniphest Tasks'), 'href' => "/search/attach/{$revision_phid}/TASK/", 'sigil' => 'workflow', ); } if ($user->getIsAdmin()) { $links[] = array( 'icon' => 'file', 'name' => pht('MetaMTA Transcripts'), 'href' => "/mail/?phid={$revision_phid}", ); } $links[] = array( 'icon' => 'file', 'name' => pht('Herald Transcripts'), 'href' => "/herald/transcript/?phid={$revision_phid}", ); } $request_uri = $this->getRequest()->getRequestURI(); $links[] = array( 'icon' => 'download', 'name' => pht('Download Raw Diff'), 'href' => $request_uri->alter('download', 'true') ); return $links; } private function getRevisionCommentActions(DifferentialRevision $revision) { $actions = array( DifferentialAction::ACTION_COMMENT => true, ); $viewer = $this->getRequest()->getUser(); $viewer_phid = $viewer->getPHID(); $viewer_is_owner = ($viewer_phid == $revision->getAuthorPHID()); $viewer_is_reviewer = in_array($viewer_phid, $revision->getReviewers()); $viewer_did_accept = ($viewer_phid === $revision->loadReviewedBy()); $status = $revision->getStatus(); $allow_self_accept = PhabricatorEnv::getEnvConfig( 'differential.allow-self-accept'); $always_allow_close = PhabricatorEnv::getEnvConfig( 'differential.always-allow-close'); $allow_reopen = PhabricatorEnv::getEnvConfig( 'differential.allow-reopen'); if ($viewer_is_owner) { switch ($status) { case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW: $actions[DifferentialAction::ACTION_ACCEPT] = $allow_self_accept; $actions[DifferentialAction::ACTION_ABANDON] = true; $actions[DifferentialAction::ACTION_RETHINK] = true; break; case ArcanistDifferentialRevisionStatus::NEEDS_REVISION: $actions[DifferentialAction::ACTION_ACCEPT] = $allow_self_accept; $actions[DifferentialAction::ACTION_ABANDON] = true; $actions[DifferentialAction::ACTION_REQUEST] = true; break; case ArcanistDifferentialRevisionStatus::ACCEPTED: $actions[DifferentialAction::ACTION_ABANDON] = true; $actions[DifferentialAction::ACTION_REQUEST] = true; $actions[DifferentialAction::ACTION_RETHINK] = true; $actions[DifferentialAction::ACTION_CLOSE] = true; break; case ArcanistDifferentialRevisionStatus::CLOSED: break; case ArcanistDifferentialRevisionStatus::ABANDONED: $actions[DifferentialAction::ACTION_RECLAIM] = true; break; } } else { switch ($status) { case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW: $actions[DifferentialAction::ACTION_ACCEPT] = true; $actions[DifferentialAction::ACTION_REJECT] = true; $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer; break; case ArcanistDifferentialRevisionStatus::NEEDS_REVISION: $actions[DifferentialAction::ACTION_ACCEPT] = true; $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer; break; case ArcanistDifferentialRevisionStatus::ACCEPTED: $actions[DifferentialAction::ACTION_REJECT] = true; $actions[DifferentialAction::ACTION_RESIGN] = $viewer_is_reviewer && !$viewer_did_accept; break; case ArcanistDifferentialRevisionStatus::CLOSED: case ArcanistDifferentialRevisionStatus::ABANDONED: break; } if ($status != ArcanistDifferentialRevisionStatus::CLOSED) { $actions[DifferentialAction::ACTION_CLAIM] = true; $actions[DifferentialAction::ACTION_CLOSE] = $always_allow_close; } } $actions[DifferentialAction::ACTION_ADDREVIEWERS] = true; $actions[DifferentialAction::ACTION_ADDCCS] = true; $actions[DifferentialAction::ACTION_REOPEN] = $allow_reopen && ($status == ArcanistDifferentialRevisionStatus::CLOSED); $actions = array_keys(array_filter($actions)); $actions_dict = array(); foreach ($actions as $action) { $actions_dict[$action] = DifferentialAction::getActionVerb($action); } return $actions_dict; } private function loadInlineComments(array $comments, array &$changesets) { assert_instances_of($comments, 'DifferentialComment'); assert_instances_of($changesets, 'DifferentialChangeset'); $inline_comments = array(); $comment_ids = array_filter(mpull($comments, 'getID')); if (!$comment_ids) { return $inline_comments; } $inline_comments = id(new DifferentialInlineComment()) ->loadAllWhere( 'commentID in (%Ld)', $comment_ids); $load_changesets = array(); foreach ($inline_comments as $inline) { $changeset_id = $inline->getChangesetID(); if (isset($changesets[$changeset_id])) { continue; } $load_changesets[$changeset_id] = true; } $more_changesets = array(); if ($load_changesets) { $changeset_ids = array_keys($load_changesets); $more_changesets += id(new DifferentialChangeset()) ->loadAllWhere( 'id IN (%Ld)', $changeset_ids); } if ($more_changesets) { $changesets += $more_changesets; $changesets = msort($changesets, 'getSortKey'); } return $inline_comments; } private function loadChangesetsAndVsMap( DifferentialDiff $target, DifferentialDiff $diff_vs = null, PhabricatorRepository $repository = null) { $load_ids = array(); if ($diff_vs) { $load_ids[] = $diff_vs->getID(); } $load_ids[] = $target->getID(); $raw_changesets = id(new DifferentialChangeset()) ->loadAllWhere( 'diffID IN (%Ld)', $load_ids); $changeset_groups = mgroup($raw_changesets, 'getDiffID'); $changesets = idx($changeset_groups, $target->getID(), array()); $changesets = mpull($changesets, null, 'getID'); $refs = array(); $vs_map = array(); $vs_changesets = array(); if ($diff_vs) { $vs_id = $diff_vs->getID(); $vs_changesets_path_map = array(); foreach (idx($changeset_groups, $vs_id, array()) as $changeset) { $path = $changeset->getAbsoluteRepositoryPath($repository, $diff_vs); $vs_changesets_path_map[$path] = $changeset; $vs_changesets[$changeset->getID()] = $changeset; } foreach ($changesets as $key => $changeset) { $path = $changeset->getAbsoluteRepositoryPath($repository, $target); if (isset($vs_changesets_path_map[$path])) { $vs_map[$changeset->getID()] = $vs_changesets_path_map[$path]->getID(); $refs[$changeset->getID()] = $changeset->getID().'/'.$vs_changesets_path_map[$path]->getID(); unset($vs_changesets_path_map[$path]); } else { $refs[$changeset->getID()] = $changeset->getID(); } } foreach ($vs_changesets_path_map as $path => $changeset) { $changesets[$changeset->getID()] = $changeset; $vs_map[$changeset->getID()] = -1; $refs[$changeset->getID()] = $changeset->getID().'/-1'; } } else { foreach ($changesets as $changeset) { $refs[$changeset->getID()] = $changeset->getID(); } } $changesets = msort($changesets, 'getSortKey'); return array($changesets, $vs_map, $vs_changesets, $refs); } private function loadAuxiliaryFields(DifferentialRevision $revision) { $aux_fields = DifferentialFieldSelector::newSelector() ->getFieldSpecifications(); foreach ($aux_fields as $key => $aux_field) { if (!$aux_field->shouldAppearOnRevisionView()) { unset($aux_fields[$key]); } else { $aux_field->setUser($this->getRequest()->getUser()); } } $aux_fields = DifferentialAuxiliaryField::loadFromStorage( $revision, $aux_fields); return $aux_fields; } private function buildSymbolIndexes( PhabricatorRepositoryArcanistProject $arc_project, array $visible_changesets) { assert_instances_of($visible_changesets, 'DifferentialChangeset'); $engine = PhabricatorSyntaxHighlighter::newEngine(); $langs = $arc_project->getSymbolIndexLanguages(); if (!$langs) { return array(array(), array()); } $symbol_indexes = array(); $project_phids = array_merge( array($arc_project->getPHID()), nonempty($arc_project->getSymbolIndexProjects(), array())); $indexed_langs = array_fill_keys($langs, true); foreach ($visible_changesets as $key => $changeset) { $lang = $engine->getLanguageFromFilename($changeset->getFilename()); if (isset($indexed_langs[$lang])) { $symbol_indexes[$key] = array( 'lang' => $lang, 'projects' => $project_phids, ); } } return array($symbol_indexes, $project_phids); } private function loadOtherRevisions( array $changesets, DifferentialDiff $target, PhabricatorRepository $repository) { assert_instances_of($changesets, 'DifferentialChangeset'); $paths = array(); foreach ($changesets as $changeset) { $paths[] = $changeset->getAbsoluteRepositoryPath( $repository, $target); } if (!$paths) { return array(); } $path_map = id(new DiffusionPathIDQuery($paths))->loadPathIDs(); if (!$path_map) { return array(); } $query = id(new DifferentialRevisionQuery()) ->withStatus(DifferentialRevisionQuery::STATUS_OPEN) ->setOrder(DifferentialRevisionQuery::ORDER_PATH_MODIFIED) ->setLimit(10) ->needRelationships(true); foreach ($path_map as $path => $path_id) { $query->withPath($repository->getID(), $path_id); } $results = $query->execute(); // Strip out *this* revision. foreach ($results as $key => $result) { if ($result->getID() == $this->revisionID) { unset($results[$key]); } } return $results; } private function renderOtherRevisions(array $revisions) { assert_instances_of($revisions, 'DifferentialRevision'); $view = id(new DifferentialRevisionListView()) ->setRevisions($revisions) ->setFields(DifferentialRevisionListView::getDefaultFields()) ->setUser($this->getRequest()->getUser()) ->loadAssets(); $phids = $view->getRequiredHandlePHIDs(); $handles = $this->loadViewerHandles($phids); $view->setHandles($handles); return id(new PhabricatorHeaderView()) ->setHeader(pht('Open Revisions Affecting These Files')) ->render(). '
'. $view->render(). '
'; } /** * Straight copy of the loadFileByPhid method in * @{class:DifferentialReviewRequestMail}. * * This is because of the code similarity between the buildPatch method in * @{class:DifferentialReviewRequestMail} and @{method:buildRawDiffResponse} * in this class. Both of these methods end up using call_user_func and this * piece of code is the lucky function. * * @return mixed (@{class:PhabricatorFile} if found, null if not) */ public function loadFileByPHID($phid) { $file = id(new PhabricatorFile())->loadOneWhere( 'phid = %s', $phid); if (!$file) { return null; } return $file->loadFileData(); } /** * Note this code is somewhat similar to the buildPatch method in * @{class:DifferentialReviewRequestMail}. * * @return @{class:AphrontRedirectResponse} */ private function buildRawDiffResponse( array $changesets, array $vs_changesets, array $vs_map, PhabricatorRepository $repository = null) { assert_instances_of($changesets, 'DifferentialChangeset'); assert_instances_of($vs_changesets, 'DifferentialChangeset'); $engine = new PhabricatorDifferenceEngine(); $generated_changesets = array(); foreach ($changesets as $changeset) { $changeset->attachHunks($changeset->loadHunks()); $right = $changeset->makeNewFile(); $choice = $changeset; $vs = idx($vs_map, $changeset->getID()); if ($vs == -1) { $left = $right; $right = $changeset->makeOldFile(); } else if ($vs) { $choice = $vs_changeset = $vs_changesets[$vs]; $vs_changeset->attachHunks($vs_changeset->loadHunks()); $left = $vs_changeset->makeNewFile(); } else { $left = $changeset->makeOldFile(); } $synthetic = $engine->generateChangesetFromFileContent( $left, $right); if (!$synthetic->getAffectedLineCount()) { $filetype = $choice->getFileType(); if ($filetype == DifferentialChangeType::FILE_TEXT || $filetype == DifferentialChangeType::FILE_SYMLINK) { continue; } } $choice->attachHunks($synthetic->getHunks()); $generated_changesets[] = $choice; } $diff = new DifferentialDiff(); $diff->attachChangesets($generated_changesets); $diff_dict = $diff->getDiffDict(); $changes = array(); foreach ($diff_dict['changes'] as $changedict) { $changes[] = ArcanistDiffChange::newFromDictionary($changedict); } $bundle = ArcanistBundle::newFromChanges($changes); $bundle->setLoadFileDataCallback(array($this, 'loadFileByPHID')); $vcs = $repository ? $repository->getVersionControlSystem() : null; switch ($vcs) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $raw_diff = $bundle->toGitPatch(); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: default: $raw_diff = $bundle->toUnifiedDiff(); break; } $request_uri = $this->getRequest()->getRequestURI(); // this ends up being something like // D123.diff // or the verbose // D123.vs123.id123.whitespaceignore-all.diff // lame but nice to include these options $file_name = ltrim($request_uri->getPath(), '/').'.'; foreach ($request_uri->getQueryParams() as $key => $value) { if ($key == 'download') { continue; } $file_name .= $key.$value.'.'; } $file_name .= 'diff'; $file = PhabricatorFile::buildFromFileDataOrHash( $raw_diff, array( 'name' => $file_name, )); return id(new AphrontRedirectResponse())->setURI($file->getBestURI()); } } diff --git a/src/applications/differential/storage/DifferentialDiff.php b/src/applications/differential/storage/DifferentialDiff.php index da3c7b8b4..11e4a754b 100644 --- a/src/applications/differential/storage/DifferentialDiff.php +++ b/src/applications/differential/storage/DifferentialDiff.php @@ -1,292 +1,294 @@ changesets === null) { $this->changesets = array(); } $this->unsavedChangesets[] = $changeset; $this->changesets[] = $changeset; return $this; } public function attachChangesets(array $changesets) { assert_instances_of($changesets, 'DifferentialChangeset'); $this->changesets = $changesets; return $this; } public function getChangesets() { if ($this->changesets === null) { throw new Exception("Must load and attach changesets first!"); } return $this->changesets; } public function loadChangesets() { if (!$this->getID()) { return array(); } return id(new DifferentialChangeset())->loadAllWhere( 'diffID = %d', $this->getID()); } public function loadArcanistProject() { if (!$this->getArcanistProjectPHID()) { return null; } return id(new PhabricatorRepositoryArcanistProject())->loadOneWhere( 'phid = %s', $this->getArcanistProjectPHID()); } public function getBackingVersionControlSystem() { $arcanist_project = $this->loadArcanistProject(); if (!$arcanist_project) { return null; } $repository = $arcanist_project->loadRepository(); if (!$repository) { return null; } return $repository->getVersionControlSystem(); } public function save() { $this->openTransaction(); $ret = parent::save(); foreach ($this->unsavedChangesets as $changeset) { $changeset->setDiffID($this->getID()); $changeset->save(); } $this->saveTransaction(); return $ret; } public function delete() { $this->openTransaction(); foreach ($this->loadChangesets() as $changeset) { $changeset->delete(); } $properties = id(new DifferentialDiffProperty())->loadAllWhere( 'diffID = %d', $this->getID()); foreach ($properties as $prop) { $prop->delete(); } $ret = parent::delete(); $this->saveTransaction(); return $ret; } public static function newFromRawChanges(array $changes) { assert_instances_of($changes, 'ArcanistDiffChange'); $diff = new DifferentialDiff(); $lines = 0; foreach ($changes as $change) { if ($change->getType() == ArcanistDiffChangeType::TYPE_MESSAGE) { // If a user pastes a diff into Differential which includes a commit // message (e.g., they ran `git show` to generate it), discard that // change when constructing a DifferentialDiff. continue; } $changeset = new DifferentialChangeset(); $add_lines = 0; $del_lines = 0; $first_line = PHP_INT_MAX; $hunks = $change->getHunks(); if ($hunks) { foreach ($hunks as $hunk) { $dhunk = new DifferentialHunk(); $dhunk->setOldOffset($hunk->getOldOffset()); $dhunk->setOldLen($hunk->getOldLength()); $dhunk->setNewOffset($hunk->getNewOffset()); $dhunk->setNewLen($hunk->getNewLength()); $dhunk->setChanges($hunk->getCorpus()); $changeset->addUnsavedHunk($dhunk); $add_lines += $hunk->getAddLines(); $del_lines += $hunk->getDelLines(); $added_lines = $hunk->getChangedLines('new'); if ($added_lines) { $first_line = min($first_line, head_key($added_lines)); } } $lines += $add_lines + $del_lines; } else { // This happens when you add empty files. $changeset->attachHunks(array()); } $metadata = $change->getAllMetadata(); if ($first_line != PHP_INT_MAX) { $metadata['line:first'] = $first_line; } $changeset->setOldFile($change->getOldPath()); $changeset->setFilename($change->getCurrentPath()); $changeset->setChangeType($change->getType()); $changeset->setFileType($change->getFileType()); $changeset->setMetadata($metadata); $changeset->setOldProperties($change->getOldProperties()); $changeset->setNewProperties($change->getNewProperties()); $changeset->setAwayPaths($change->getAwayPaths()); $changeset->setAddLines($add_lines); $changeset->setDelLines($del_lines); $diff->addUnsavedChangeset($changeset); } $diff->setLineCount($lines); $parser = new DifferentialChangesetParser(); $changesets = $parser->detectCopiedCode( $diff->getChangesets(), $min_width = 30, $min_lines = 3); $diff->attachChangesets($changesets); return $diff; } public function getDiffDict() { $dict = array( 'id' => $this->getID(), 'parent' => $this->getParentRevisionID(), 'revisionID' => $this->getRevisionID(), + 'dateCreated' => $this->getDateCreated(), + 'dateModified' => $this->getDateModified(), 'sourceControlBaseRevision' => $this->getSourceControlBaseRevision(), 'sourceControlPath' => $this->getSourceControlPath(), 'sourceControlSystem' => $this->getSourceControlSystem(), 'branch' => $this->getBranch(), 'bookmark' => $this->getBookmark(), 'creationMethod' => $this->getCreationMethod(), 'description' => $this->getDescription(), 'unitStatus' => $this->getUnitStatus(), 'lintStatus' => $this->getLintStatus(), 'changes' => array(), 'properties' => array(), ); foreach ($this->getChangesets() as $changeset) { $hunks = array(); foreach ($changeset->getHunks() as $hunk) { $hunks[] = array( 'oldOffset' => $hunk->getOldOffset(), 'newOffset' => $hunk->getNewOffset(), 'oldLength' => $hunk->getOldLen(), 'newLength' => $hunk->getNewLen(), 'addLines' => null, 'delLines' => null, 'isMissingOldNewline' => null, 'isMissingNewNewline' => null, 'corpus' => $hunk->getChanges(), ); } $change = array( 'metadata' => $changeset->getMetadata(), 'oldPath' => $changeset->getOldFile(), 'currentPath' => $changeset->getFilename(), 'awayPaths' => $changeset->getAwayPaths(), 'oldProperties' => $changeset->getOldProperties(), 'newProperties' => $changeset->getNewProperties(), 'type' => $changeset->getChangeType(), 'fileType' => $changeset->getFileType(), 'commitHash' => null, 'addLines' => $changeset->getAddLines(), 'delLines' => $changeset->getDelLines(), 'hunks' => $hunks, ); $dict['changes'][] = $change; } $properties = id(new DifferentialDiffProperty())->loadAllWhere( 'diffID = %d', $this->getID()); foreach ($properties as $property) { $dict['properties'][$property->getName()] = $property->getData(); } return $dict; } /** * Figures out the right author information for a given diff based on the * repository and Phabricator configuration settings. * * Git is particularly finicky as it requires author information to be in * the format "George Washington " to * consistently work. If the Phabricator instance isn't configured to * expose emails prudently, then we are unable to get any author information * for git. */ public function loadAuthorInformation() { $author = id(new PhabricatorUser()) ->loadOneWhere('phid = %s', $this->getAuthorPHID()); $use_emails = PhabricatorEnv::getEnvConfig('differential.expose-emails-prudently'); switch ($this->getSourceControlSystem()) { case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: if (!$use_emails) { $author_info = ''; } else { $author_info = $this->getFullAuthorInfo($author); } break; case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: if (!$use_emails) { $author_info = $author->getUsername(); } else { $author_info = $this->getFullAuthorInfo($author); } break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: default: $author_info = $author->getUsername(); break; } return $author_info; } private function getFullAuthorInfo(PhabricatorUser $author) { return sprintf('%s <%s>', $author->getRealName(), $author->loadPrimaryEmailAddress()); } } diff --git a/src/applications/differential/view/DifferentialChangesetListView.php b/src/applications/differential/view/DifferentialChangesetListView.php index 00094164f..11209f000 100644 --- a/src/applications/differential/view/DifferentialChangesetListView.php +++ b/src/applications/differential/view/DifferentialChangesetListView.php @@ -1,319 +1,319 @@ title = $title; return $this; } private function getTitle() { return $this->title; } public function setBranch($branch) { $this->branch = $branch; return $this; } private function getBranch() { return $this->branch; } public function setChangesets($changesets) { $this->changesets = $changesets; return $this; } public function setVisibleChangesets($visible_changesets) { $this->visibleChangesets = $visible_changesets; return $this; } public function setInlineCommentControllerURI($uri) { $this->inlineURI = $uri; return $this; } public function setRepository(PhabricatorRepository $repository) { $this->repository = $repository; return $this; } public function setDiff(DifferentialDiff $diff) { $this->diff = $diff; return $this; } public function setRenderingReferences(array $references) { $this->references = $references; return $this; } public function setSymbolIndexes(array $indexes) { $this->symbolIndexes = $indexes; return $this; } public function setRenderURI($render_uri) { $this->renderURI = $render_uri; return $this; } public function setWhitespace($whitespace) { $this->whitespace = $whitespace; return $this; } public function setVsMap(array $vs_map) { $this->vsMap = $vs_map; return $this; } public function getVsMap() { return $this->vsMap; } public function setStandaloneURI($uri) { $this->standaloneURI = $uri; return $this; } public function setRawFileURIs($l, $r) { $this->leftRawFileURI = $l; $this->rightRawFileURI = $r; return $this; } public function render() { require_celerity_resource('differential-changeset-view-css'); $changesets = $this->changesets; Javelin::initBehavior('differential-toggle-files', array()); $output = array(); $mapping = array(); foreach ($changesets as $key => $changeset) { $file = $changeset->getFilename(); $class = 'differential-changeset'; if (!$this->inlineURI) { $class .= ' differential-changeset-noneditable'; } $ref = $this->references[$key]; $detail = new DifferentialChangesetDetailView(); $view_options = $this->renderViewOptionsDropdown( $detail, $ref, $changeset); $prefs = $this->user->loadPreferences(); $pref_symbols = $prefs->getPreference( PhabricatorUserPreferences::PREFERENCE_DIFFUSION_SYMBOLS); $detail->setChangeset($changeset); $detail->addButton($view_options); if ($pref_symbols != 'disabled') { $detail->setSymbolIndex(idx($this->symbolIndexes, $key)); } $detail->setVsChangesetID(idx($this->vsMap, $changeset->getID())); $detail->setEditable(true); $uniq_id = 'diff-'.$changeset->getAnchorName(); if (isset($this->visibleChangesets[$key])) { $load = 'Loading...'; $mapping[$uniq_id] = $ref; } else { $load = javelin_tag( 'a', array( 'href' => '#'.$uniq_id, 'meta' => array( 'id' => $uniq_id, 'ref' => $ref, 'kill' => true, ), 'sigil' => 'differential-load', 'mustcapture' => true, ), pht('Load')); } $detail->appendChild( phutil_tag( 'div', array( 'id' => $uniq_id, ), phutil_tag('div', array('class' => 'differential-loading'), $load))); $output[] = $detail->render(); } require_celerity_resource('aphront-tooltip-css'); Javelin::initBehavior('differential-populate', array( 'registry' => $mapping, 'whitespace' => $this->whitespace, 'uri' => $this->renderURI, )); Javelin::initBehavior('differential-show-more', array( 'uri' => $this->renderURI, 'whitespace' => $this->whitespace, )); Javelin::initBehavior('differential-comment-jump', array()); if ($this->inlineURI) { $undo_templates = $this->renderUndoTemplates(); Javelin::initBehavior('differential-edit-inline-comments', array( 'uri' => $this->inlineURI, 'undo_templates' => $undo_templates, 'stage' => 'differential-review-stage', )); } return $this->renderHTMLView( array( id(new PhabricatorHeaderView()) ->setHeader($this->getTitle()) ->render(), phutil_tag( 'div', array( 'class' => 'differential-review-stage', 'id' => 'differential-review-stage', ), $output), )); } /** * Render the "Undo" markup for the inline comment undo feature. */ private function renderUndoTemplates() { $link = javelin_tag( 'a', array( 'href' => '#', 'sigil' => 'differential-inline-comment-undo', ), pht('Undo')); $div = phutil_tag( 'div', array( 'class' => 'differential-inline-undo', ), array('Changes discarded. ', $link)); $template = ''. ''. - ''. + ''. '
%s%s%s
'; return array( 'l' => sprintf($template, $div, ''), 'r' => sprintf($template, '', $div), ); } private function renderViewOptionsDropdown( DifferentialChangesetDetailView $detail, $ref, DifferentialChangeset $changeset) { $meta = array(); $qparams = array( 'ref' => $ref, 'whitespace' => $this->whitespace, ); if ($this->standaloneURI) { $uri = new PhutilURI($this->standaloneURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['standaloneURI'] = (string)$uri; } $repository = $this->repository; if ($repository) { $meta['diffusionURI'] = (string)$repository->getDiffusionBrowseURIForPath( $changeset->getAbsoluteRepositoryPath($repository, $this->diff), idx($changeset->getMetadata(), 'line:first'), $this->getBranch()); } $change = $changeset->getChangeType(); if ($this->leftRawFileURI) { if ($change != DifferentialChangeType::TYPE_ADD) { $uri = new PhutilURI($this->leftRawFileURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['leftURI'] = (string)$uri; } } if ($this->rightRawFileURI) { if ($change != DifferentialChangeType::TYPE_DELETE && $change != DifferentialChangeType::TYPE_MULTICOPY) { $uri = new PhutilURI($this->rightRawFileURI); $uri->setQueryParams($uri->getQueryParams() + $qparams); $meta['rightURI'] = (string)$uri; } } $user = $this->user; if ($user && $repository) { $path = ltrim( $changeset->getAbsoluteRepositoryPath($repository, $this->diff), '/'); $line = idx($changeset->getMetadata(), 'line:first', 1); $callsign = $repository->getCallsign(); $editor_link = $user->loadEditorLink($path, $line, $callsign); if ($editor_link) { $meta['editor'] = $editor_link; } else { $meta['editorConfigure'] = '/settings/panel/display/'; } } $meta['containerID'] = $detail->getID(); Javelin::initBehavior( 'differential-dropdown-menus', array()); return javelin_tag( 'a', array( 'class' => 'button small grey', 'meta' => $meta, 'href' => idx($meta, 'detailURI', '#'), 'target' => '_blank', 'sigil' => 'differential-view-options', ), pht("View Options \xE2\x96\xBC")); } } diff --git a/src/applications/differential/view/DifferentialRevisionDetailView.php b/src/applications/differential/view/DifferentialRevisionDetailView.php index 118201295..55204ed32 100644 --- a/src/applications/differential/view/DifferentialRevisionDetailView.php +++ b/src/applications/differential/view/DifferentialRevisionDetailView.php @@ -1,112 +1,113 @@ diff = $diff; return $this; } private function getDiff() { return $this->diff; } public function setRevision(DifferentialRevision $revision) { $this->revision = $revision; return $this; } public function setActions(array $actions) { $this->actions = $actions; return $this; } private function getActions() { return $this->actions; } public function setAuxiliaryFields(array $fields) { assert_instances_of($fields, 'DifferentialFieldSpecification'); $this->auxiliaryFields = $fields; return $this; } public function render() { require_celerity_resource('differential-core-view-css'); $revision = $this->revision; $user = $this->getUser(); $header = $this->renderHeader($revision); $actions = id(new PhabricatorActionListView()) ->setUser($user) ->setObject($revision); foreach ($this->getActions() as $action) { $obj = id(new PhabricatorActionView()) ->setIcon(idx($action, 'icon', 'edit')) ->setName($action['name']) ->setHref(idx($action, 'href')) ->setWorkflow(idx($action, 'sigil') == 'workflow') + ->setRenderAsForm(!empty($action['instant'])) ->setUser($user) ->setDisabled(idx($action, 'disabled', false)); $actions->addAction($obj); } $properties = new PhabricatorPropertyListView(); $status = $revision->getStatus(); $local_vcs = $this->getDiff()->getSourceControlSystem(); $next_step = null; if ($status == ArcanistDifferentialRevisionStatus::ACCEPTED) { switch ($local_vcs) { case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: $next_step = phutil_tag('tt', array(), 'arc land'); break; case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: $next_step = phutil_tag('tt', array(), 'arc commit'); break; } } if ($next_step) { $properties->addProperty(pht('Next Step'), $next_step); } foreach ($this->auxiliaryFields as $field) { $value = $field->renderValueForRevisionView(); if (strlen($value)) { $label = rtrim($field->renderLabelForRevisionView(), ':'); $properties->addProperty($label, $value); } } $properties->setHasKeyboardShortcuts(true); return $header->render() . $actions->render() . $properties->render(); } private function renderHeader(DifferentialRevision $revision) { $view = id(new PhabricatorHeaderView()) ->setObjectName('D'.$revision->getID()) ->setHeader($revision->getTitle()); $status = $revision->getStatus(); $status_name = ArcanistDifferentialRevisionStatus::getNameForRevisionStatus($status); $status_color = DifferentialRevisionStatus::getRevisionStatusTagColor($status); $view->addTag( id(new PhabricatorTagView()) ->setType(PhabricatorTagView::TYPE_STATE) ->setName($status_name) ->setBackgroundColor($status_color) ); return $view; } } diff --git a/src/applications/diffusion/controller/DiffusionBrowseFileController.php b/src/applications/diffusion/controller/DiffusionBrowseFileController.php index f89e6ef7c..fa7686699 100644 --- a/src/applications/diffusion/controller/DiffusionBrowseFileController.php +++ b/src/applications/diffusion/controller/DiffusionBrowseFileController.php @@ -1,955 +1,955 @@ getRequest(); $drequest = $this->getDiffusionRequest(); $before = $request->getStr('before'); if ($before) { return $this->buildBeforeResponse($before); } $path = $drequest->getPath(); $selected = $request->getStr('view'); $preferences = $request->getUser()->loadPreferences(); if (!$selected) { $selected = $preferences->getPreference( PhabricatorUserPreferences::PREFERENCE_DIFFUSION_VIEW, 'highlighted'); } else if ($request->isFormPost() && $selected != 'raw') { $preferences->setPreference( PhabricatorUserPreferences::PREFERENCE_DIFFUSION_VIEW, $selected); $preferences->save(); return id(new AphrontRedirectResponse()) ->setURI($request->getRequestURI()->alter('view', $selected)); } $needs_blame = ($selected == 'blame' || $selected == 'plainblame'); $file_query = DiffusionFileContentQuery::newFromDiffusionRequest( $this->diffusionRequest); $file_query->setViewer($request->getUser()); $file_query->setNeedsBlame($needs_blame); $file_query->loadFileContent(); $data = $file_query->getRawData(); if ($selected === 'raw') { return $this->buildRawResponse($path, $data); } $this->loadLintMessages(); // Build the content of the file. $corpus = $this->buildCorpus( $selected, $file_query, $needs_blame, $drequest, $path, $data); require_celerity_resource('diffusion-source-css'); if ($this->corpusType == 'text') { $view_select_panel = $this->renderViewSelectPanel($selected); } else { $view_select_panel = null; } // Render the page. $content = array(); $follow = $request->getStr('follow'); if ($follow) { $notice = new AphrontErrorView(); $notice->setSeverity(AphrontErrorView::SEVERITY_WARNING); $notice->setTitle('Unable to Continue'); switch ($follow) { case 'first': $notice->appendChild( "Unable to continue tracing the history of this file because ". "this commit is the first commit in the repository."); break; case 'created': $notice->appendChild( "Unable to continue tracing the history of this file because ". "this commit created the file."); break; } $content[] = $notice; } $renamed = $request->getStr('renamed'); if ($renamed) { $notice = new AphrontErrorView(); $notice->setSeverity(AphrontErrorView::SEVERITY_NOTICE); $notice->setTitle('File Renamed'); $notice->appendChild( "File history passes through a rename from '". phutil_escape_html($drequest->getPath())."' to '". phutil_escape_html($renamed)."'."); $content[] = $notice; } $content[] = $view_select_panel; $content[] = $corpus; $content[] = $this->buildOpenRevisions(); $nav = $this->buildSideNav('browse', true); $nav->appendChild($content); $crumbs = $this->buildCrumbs( array( 'branch' => true, 'path' => true, 'view' => 'browse', )); $nav->setCrumbs($crumbs); $basename = basename($this->getDiffusionRequest()->getPath()); return $this->buildApplicationPage( $nav, array( 'title' => $basename, )); } private function loadLintMessages() { $drequest = $this->getDiffusionRequest(); $branch = $drequest->loadBranch(); if (!$branch || !$branch->getLintCommit()) { return; } $this->lintCommit = $branch->getLintCommit(); $conn = id(new PhabricatorRepository())->establishConnection('r'); $where = ''; if ($drequest->getLint()) { $where = qsprintf( $conn, 'AND code = %s', $drequest->getLint()); } $this->lintMessages = queryfx_all( $conn, 'SELECT * FROM %T WHERE branchID = %d %Q AND path = %s', PhabricatorRepository::TABLE_LINTMESSAGE, $branch->getID(), $where, '/'.$drequest->getPath()); } private function buildCorpus($selected, DiffusionFileContentQuery $file_query, $needs_blame, DiffusionRequest $drequest, $path, $data) { if (ArcanistDiffUtils::isHeuristicBinaryFile($data)) { $file = $this->loadFileForData($path, $data); $file_uri = $file->getBestURI(); if ($file->isViewableImage()) { $this->corpusType = 'image'; return $this->buildImageCorpus($file_uri); } else { $this->corpusType = 'binary'; return $this->buildBinaryCorpus($file_uri, $data); } } switch ($selected) { case 'plain': $style = "margin: 1em 2em; width: 90%; height: 80em; font-family: monospace"; $corpus = phutil_tag( 'textarea', array( 'style' => $style, ), $file_query->getRawData()); break; case 'plainblame': $style = "margin: 1em 2em; width: 90%; height: 80em; font-family: monospace"; list($text_list, $rev_list, $blame_dict) = $file_query->getBlameData(); $rows = array(); foreach ($text_list as $k => $line) { $rev = $rev_list[$k]; if (isset($blame_dict[$rev]['handle'])) { $author = $blame_dict[$rev]['handle']->getName(); } else { $author = $blame_dict[$rev]['author']; } $rows[] = sprintf("%-10s %-20s %s", substr($rev, 0, 7), $author, $line); } $corpus = phutil_tag( 'textarea', array( 'style' => $style, ), implode("\n", $rows)); break; case 'highlighted': case 'blame': default: require_celerity_resource('syntax-highlighting-css'); list($text_list, $rev_list, $blame_dict) = $file_query->getBlameData(); $text_list = implode("\n", $text_list); $text_list = PhabricatorSyntaxHighlighter::highlightWithFilename( $path, $text_list); $text_list = explode("\n", $text_list); $rows = $this->buildDisplayRows($text_list, $rev_list, $blame_dict, $needs_blame, $drequest, $file_query, $selected); $id = celerity_generate_unique_node_id(); $projects = $drequest->loadArcanistProjects(); $langs = array(); foreach ($projects as $project) { $ls = $project->getSymbolIndexLanguages(); if (!$ls) { continue; } $dep_projects = $project->getSymbolIndexProjects(); $dep_projects[] = $project->getPHID(); foreach ($ls as $lang) { if (!isset($langs[$lang])) { $langs[$lang] = array(); } $langs[$lang] += $dep_projects + array($project); } } $lang = last(explode('.', $drequest->getPath())); $prefs = $this->getRequest()->getUser()->loadPreferences(); $pref_symbols = $prefs->getPreference( PhabricatorUserPreferences::PREFERENCE_DIFFUSION_SYMBOLS); if (isset($langs[$lang]) && $pref_symbols != 'disabled') { Javelin::initBehavior( 'repository-crossreference', array( 'container' => $id, 'lang' => $lang, 'projects' => $langs[$lang], )); } $corpus_table = javelin_tag( 'table', array( 'class' => "diffusion-source remarkup-code PhabricatorMonospaced", 'sigil' => 'diffusion-source', ), $rows); $corpus = phutil_tag( 'div', array( 'style' => 'padding: 0 2em;', 'id' => $id, ), $corpus_table); break; } return $corpus; } private function renderViewSelectPanel($selected) { $toggle_blame = array( 'highlighted' => 'blame', 'blame' => 'highlighted', 'plain' => 'plainblame', 'plainblame' => 'plain', 'raw' => 'raw', // not a real case. ); $toggle_highlight = array( 'highlighted' => 'plain', 'blame' => 'plainblame', 'plain' => 'highlighted', 'plainblame' => 'blame', 'raw' => 'raw', // not a real case. ); $user = $this->getRequest()->getUser(); $base_uri = $this->getRequest()->getRequestURI(); $blame_on = ($selected == 'blame' || $selected == 'plainblame'); if ($blame_on) { $blame_text = pht('Disable Blame'); } else { $blame_text = pht('Enable Blame'); } $blame_button = $this->createViewAction( $blame_text, $base_uri->alter('view', $toggle_blame[$selected]), $user); $highlight_on = ($selected == 'blame' || $selected == 'highlighted'); if ($highlight_on) { $highlight_text = pht('Disable Highlighting'); } else { $highlight_text = pht('Enable Highlighting'); } $highlight_button = $this->createViewAction( $highlight_text, $base_uri->alter('view', $toggle_highlight[$selected]), $user); $href = null; if ($this->getRequest()->getStr('lint') !== null) { $lint_text = pht('Hide %d Lint Message(s)', count($this->lintMessages)); $href = $base_uri->alter('lint', null); } else if ($this->lintCommit === null) { $lint_text = pht('Lint not Available'); } else { $lint_text = pht( 'Show %d Lint Message(s)', count($this->lintMessages)); $href = $this->getDiffusionRequest()->generateURI(array( 'action' => 'browse', 'commit' => $this->lintCommit, ))->alter('lint', ''); } $lint_button = $this->createViewAction( $lint_text, $href, $user); if (!$href) { $lint_button->setDisabled(true); } $raw_button = $this->createViewAction( pht('View Raw File'), $base_uri->alter('view', 'raw'), $user, 'file'); $edit_button = $this->createEditAction(); return id(new PhabricatorActionListView()) ->setUser($user) ->addAction($blame_button) ->addAction($highlight_button) ->addAction($lint_button) ->addAction($raw_button) ->addAction($edit_button); } private function createViewAction( $localized_text, $href, $user, $icon = null) { return id(new PhabricatorActionView()) ->setName($localized_text) ->setIcon($icon) ->setUser($user) ->setRenderAsForm(true) ->setHref($href); } private function createEditAction() { $request = $this->getRequest(); $user = $request->getUser(); $drequest = $this->getDiffusionRequest(); $repository = $drequest->getRepository(); $path = $drequest->getPath(); $line = nonempty((int)$drequest->getLine(), 1); $callsign = $repository->getCallsign(); $editor_link = $user->loadEditorLink($path, $line, $callsign); $action = id(new PhabricatorActionView()) ->setName(pht('Open in Editor')) ->setIcon('edit'); $action->setHref($editor_link); $action->setDisabled(!$editor_link); return $action; } private function buildDisplayRows( array $text_list, array $rev_list, array $blame_dict, $needs_blame, DiffusionRequest $drequest, DiffusionFileContentQuery $file_query, $selected) { if ($blame_dict) { $epoch_list = ipull(ifilter($blame_dict, 'epoch'), 'epoch'); $epoch_min = min($epoch_list); $epoch_max = max($epoch_list); $epoch_range = ($epoch_max - $epoch_min) + 1; } $line_arr = array(); $line_str = $drequest->getLine(); $ranges = explode(',', $line_str); foreach ($ranges as $range) { if (strpos($range, '-') !== false) { list($min, $max) = explode('-', $range, 2); $line_arr[] = array( 'min' => min($min, $max), 'max' => max($min, $max), ); } else if (strlen($range)) { $line_arr[] = array( 'min' => $range, 'max' => $range, ); } } $display = array(); $line_number = 1; $last_rev = null; $color = null; foreach ($text_list as $k => $line) { $display_line = array( 'color' => null, 'epoch' => null, 'commit' => null, 'author' => null, 'target' => null, 'highlighted' => null, 'line' => $line_number, 'data' => $line, ); if ($needs_blame) { // If the line's rev is same as the line above, show empty content // with same color; otherwise generate blame info. The newer a change // is, the more saturated the color. $rev = idx($rev_list, $k, $last_rev); if ($last_rev == $rev) { $display_line['color'] = $color; } else { $blame = $blame_dict[$rev]; if (!isset($blame['epoch'])) { $color = '#ffd'; // Render as warning. } else { $color_ratio = ($blame['epoch'] - $epoch_min) / $epoch_range; $color_value = 0xF6 * (1.0 - $color_ratio); $color = sprintf( '#%02x%02x%02x', $color_value, 0xF6, $color_value); } $display_line['epoch'] = idx($blame, 'epoch'); $display_line['color'] = $color; $display_line['commit'] = $rev; if (isset($blame['handle'])) { $author_link = $blame['handle']->renderLink(); } else { $author_link = phutil_tag( 'span', array( ), $blame['author']); } $display_line['author'] = $author_link; $last_rev = $rev; } } if ($line_arr) { if ($line_number == $line_arr[0]['min']) { $display_line['target'] = true; } foreach ($line_arr as $range) { if ($line_number >= $range['min'] && $line_number <= $range['max']) { $display_line['highlighted'] = true; } } } $display[] = $display_line; ++$line_number; } $commits = array_filter(ipull($display, 'commit')); if ($commits) { $commits = id(new PhabricatorAuditCommitQuery()) ->withIdentifiers($drequest->getRepository()->getID(), $commits) ->needCommitData(true) ->execute(); $commits = mpull($commits, null, 'getCommitIdentifier'); } $revision_ids = id(new DifferentialRevision()) ->loadIDsByCommitPHIDs(mpull($commits, 'getPHID')); $revisions = array(); if ($revision_ids) { $revisions = id(new DifferentialRevision())->loadAllWhere( 'id IN (%Ld)', $revision_ids); } $request = $this->getRequest(); $user = $request->getUser(); Javelin::initBehavior('phabricator-oncopy', array()); $engine = null; $inlines = array(); if ($this->getRequest()->getStr('lint') !== null && $this->lintMessages) { $engine = new PhabricatorMarkupEngine(); $engine->setViewer($user); foreach ($this->lintMessages as $message) { $inline = id(new PhabricatorAuditInlineComment()) ->setID($message['id']) ->setSyntheticAuthor( ArcanistLintSeverity::getStringForSeverity($message['severity']). ' '.$message['code'].' ('.$message['name'].')') ->setLineNumber($message['line']) ->setContent($message['description']); $inlines[$message['line']][] = $inline; $engine->addObject( $inline, PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY); } $engine->process(); require_celerity_resource('differential-changeset-view-css'); } $rows = $this->renderInlines( idx($inlines, 0, array()), $needs_blame, $engine); foreach ($display as $line) { $line_href = $drequest->generateURI( array( 'action' => 'browse', 'line' => $line['line'], 'stable' => true, )); $blame = array(); if ($line['color']) { $color = $line['color']; $before_link = null; $commit_link = null; $revision_link = null; if (idx($line, 'commit')) { $commit = $line['commit']; $summary = 'Unknown'; if (idx($commits, $commit)) { $summary = $commits[$commit]->getCommitData()->getSummary(); } $tooltip = phabricator_date( $line['epoch'], $user)." \xC2\xB7 ".$summary; Javelin::initBehavior('phabricator-tooltips', array()); require_celerity_resource('aphront-tooltip-css'); $commit_link = javelin_tag( 'a', array( 'href' => $drequest->generateURI( array( 'action' => 'commit', 'commit' => $line['commit'], )), 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => $tooltip, 'align' => 'E', 'size' => 600, ), ), phutil_utf8_shorten($line['commit'], 9, '')); $revision_id = null; if (idx($commits, $commit)) { $revision_id = idx($revision_ids, $commits[$commit]->getPHID()); } if ($revision_id) { $revision = idx($revisions, $revision_id); if (!$revision) { $tooltip = '(Invalid revision)'; } else { $tooltip = phabricator_date($revision->getDateModified(), $user). " \xC2\xB7 ". $revision->getTitle(); } $revision_link = javelin_tag( 'a', array( 'href' => '/D'.$revision_id, 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => $tooltip, 'align' => 'E', 'size' => 600, ), ), 'D'.$revision_id); } $uri = $line_href->alter('before', $commit); $before_link = javelin_tag( 'a', array( 'href' => $uri->setQueryParam('view', 'blame'), 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => 'Skip Past This Commit', 'align' => 'E', 'size' => 300, ), ), "\xC2\xAB"); } $blame[] = phutil_tag( 'th', array( 'class' => 'diffusion-blame-link', 'style' => 'background: '.$color, ), $before_link); $blame[] = phutil_tag( 'th', array( 'class' => 'diffusion-rev-link', 'style' => 'background: '.$color, ), $commit_link); $blame[] = phutil_tag( 'th', array( 'class' => 'diffusion-rev-link', 'style' => 'background: '.$color, ), $revision_link); $blame[] = phutil_tag( 'th', array( 'class' => 'diffusion-author-link', 'style' => 'background: '.$color, ), idx($line, 'author')); } $line_link = phutil_tag( 'a', array( 'href' => $line_href, ), $line['line']); $blame[] = javelin_tag( 'th', array( 'class' => 'diffusion-line-link', 'sigil' => 'diffusion-line-link', 'style' => isset($color) ? 'background: '.$color : null, ), $line_link); Javelin::initBehavior('diffusion-line-linker'); if ($line['target']) { Javelin::initBehavior( 'diffusion-jump-to', array( 'target' => 'scroll_target', )); $anchor_text = phutil_tag( 'a', array( 'id' => 'scroll_target', ), ''); } else { $anchor_text = null; } $blame[] = phutil_tag( 'td', array( ), array( $anchor_text, // NOTE: See phabricator-oncopy behavior. "\xE2\x80\x8B", // TODO: [HTML] Not ideal. phutil_safe_html($line['data']), )); $rows[] = phutil_tag( 'tr', array( 'class' => ($line['highlighted'] ? 'highlighted' : null), ), $blame); $rows = array_merge($rows, $this->renderInlines( idx($inlines, $line['line'], array()), $needs_blame, $engine)); } return $rows; } private function renderInlines(array $inlines, $needs_blame, $engine) { $rows = array(); foreach ($inlines as $inline) { $inline_view = id(new DifferentialInlineCommentView()) ->setMarkupEngine($engine) ->setInlineComment($inline) ->render(); $row = array_fill(0, ($needs_blame ? 5 : 1), phutil_tag('th')); $row[] = phutil_tag('td', array(), $inline_view); $rows[] = phutil_tag('tr', array('class' => 'inline'), $row); } return $rows; } private function loadFileForData($path, $data) { return PhabricatorFile::buildFromFileDataOrHash( $data, array( 'name' => basename($path), )); } private function buildRawResponse($path, $data) { $file = $this->loadFileForData($path, $data); return id(new AphrontRedirectResponse())->setURI($file->getBestURI()); } private function buildImageCorpus($file_uri) { $properties = new PhabricatorPropertyListView(); $properties->addProperty( pht('Image'), phutil_tag( 'img', array( 'src' => $file_uri, ))); $actions = id(new PhabricatorActionListView()) ->setUser($this->getRequest()->getUser()) ->addAction($this->createEditAction()); return array($actions, $properties); } private function buildBinaryCorpus($file_uri, $data) { $properties = new PhabricatorPropertyListView(); $size = strlen($data); $properties->addTextContent( - pht('This is a binary file. It is %2$s byte(s) in length.', - $size, - PhutilTranslator::getInstance()->formatNumber($size))); + pht( + 'This is a binary file. It is %s byte(s) in length.', + new PhutilNumber($size))); $actions = id(new PhabricatorActionListView()) ->setUser($this->getRequest()->getUser()) ->addAction($this->createEditAction()) ->addAction( id(new PhabricatorActionView()) ->setName(pht('Download Binary File...')) ->setIcon('download') ->setHref($file_uri)); return array($actions, $properties); } private function buildBeforeResponse($before) { $request = $this->getRequest(); $drequest = $this->getDiffusionRequest(); // NOTE: We need to get the grandparent so we can capture filename changes // in the parent. $parent = $this->loadParentRevisionOf($before); $old_filename = null; $was_created = false; if ($parent) { $grandparent = $this->loadParentRevisionOf( $parent->getCommitIdentifier()); if ($grandparent) { $rename_query = new DiffusionRenameHistoryQuery(); $rename_query->setRequest($drequest); $rename_query->setOldCommit($grandparent->getCommitIdentifier()); $old_filename = $rename_query->loadOldFilename(); $was_created = $rename_query->getWasCreated(); } } $follow = null; if ($was_created) { // If the file was created in history, that means older commits won't // have it. Since we know it existed at 'before', it must have been // created then; jump there. $target_commit = $before; $follow = 'created'; } else if ($parent) { // If we found a parent, jump to it. This is the normal case. $target_commit = $parent->getCommitIdentifier(); } else { // If there's no parent, this was probably created in the initial commit? // And the "was_created" check will fail because we can't identify the // grandparent. Keep the user at 'before'. $target_commit = $before; $follow = 'first'; } $path = $drequest->getPath(); $renamed = null; if ($old_filename !== null && $old_filename !== '/'.$path) { $renamed = $path; $path = $old_filename; } $line = null; // If there's a follow error, drop the line so the user sees the message. if (!$follow) { $line = $this->getBeforeLineNumber($target_commit); } $before_uri = $drequest->generateURI( array( 'action' => 'browse', 'commit' => $target_commit, 'line' => $line, 'path' => $path, )); $before_uri->setQueryParams($request->getRequestURI()->getQueryParams()); $before_uri = $before_uri->alter('before', null); $before_uri = $before_uri->alter('renamed', $renamed); $before_uri = $before_uri->alter('follow', $follow); return id(new AphrontRedirectResponse())->setURI($before_uri); } private function getBeforeLineNumber($target_commit) { $drequest = $this->getDiffusionRequest(); $line = $drequest->getLine(); if (!$line) { return null; } $diff_query = DiffusionRawDiffQuery::newFromDiffusionRequest($drequest); $diff_query->setAgainstCommit($target_commit); try { $raw_diff = $diff_query->loadRawDiff(); $old_line = 0; $new_line = 0; foreach (explode("\n", $raw_diff) as $text) { if ($text[0] == '-' || $text[0] == ' ') { $old_line++; } if ($text[0] == '+' || $text[0] == ' ') { $new_line++; } if ($new_line == $line) { return $old_line; } } // We didn't find the target line. return $line; } catch (Exception $ex) { return $line; } } private function loadParentRevisionOf($commit) { $drequest = $this->getDiffusionRequest(); $before_req = DiffusionRequest::newFromDictionary( array( 'repository' => $drequest->getRepository(), 'commit' => $commit, )); $query = DiffusionCommitParentsQuery::newFromDiffusionRequest($before_req); $parents = $query->loadParents(); return head($parents); } } diff --git a/src/applications/diffusion/controller/DiffusionCommitController.php b/src/applications/diffusion/controller/DiffusionCommitController.php index 52392e174..bb6ac15f3 100644 --- a/src/applications/diffusion/controller/DiffusionCommitController.php +++ b/src/applications/diffusion/controller/DiffusionCommitController.php @@ -1,938 +1,949 @@ diffusionRequest = $drequest; } public function processRequest() { $drequest = $this->getDiffusionRequest(); $request = $this->getRequest(); $user = $request->getUser(); if ($request->getStr('diff')) { return $this->buildRawDiffResponse($drequest); } $callsign = $drequest->getRepository()->getCallsign(); $content = array(); $repository = $drequest->getRepository(); $commit = $drequest->loadCommit(); if (!$commit) { $query = DiffusionExistsQuery::newFromDiffusionRequest($drequest); $exists = $query->loadExistentialData(); if (!$exists) { return new Aphront404Response(); } return $this->buildStandardPageResponse( id(new AphrontErrorView()) ->setTitle('Error displaying commit.') ->appendChild('Failed to load the commit because the commit has not '. 'been parsed yet.'), array('title' => 'Commit Still Parsing') ); } $commit_data = $drequest->loadCommitData(); $commit->attachCommitData($commit_data); $top_anchor = id(new PhabricatorAnchorView()) ->setAnchorName('top') ->setNavigationMarker(true); $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub'); $changesets = null; if ($is_foreign) { $subpath = $commit_data->getCommitDetail('svn-subpath'); $error_panel = new AphrontErrorView(); $error_panel->setTitle('Commit Not Tracked'); $error_panel->setSeverity(AphrontErrorView::SEVERITY_WARNING); $error_panel->appendChild( "This Diffusion repository is configured to track only one ". "subdirectory of the entire Subversion repository, and this commit ". "didn't affect the tracked subdirectory ('". phutil_escape_html($subpath)."'), so no information is available."); $content[] = $error_panel; $content[] = $top_anchor; } else { $engine = PhabricatorMarkupEngine::newDifferentialMarkupEngine(); require_celerity_resource('diffusion-commit-view-css'); require_celerity_resource('phabricator-remarkup-css'); $parent_query = DiffusionCommitParentsQuery::newFromDiffusionRequest( $drequest); $headsup_view = id(new PhabricatorHeaderView()) ->setHeader('Commit Detail'); $headsup_actions = $this->renderHeadsupActionList($commit, $repository); $commit_properties = $this->loadCommitProperties( $commit, $commit_data, $parent_query->loadParents() ); $property_list = id(new PhabricatorPropertyListView()) ->setHasKeyboardShortcuts(true); foreach ($commit_properties as $key => $value) { $property_list->addProperty($key, $value); } $property_list->addTextContent( phutil_tag( 'div', array( 'class' => 'diffusion-commit-message phabricator-remarkup', ), phutil_safe_html( $engine->markupText($commit_data->getCommitMessage())))); $content[] = $top_anchor; $content[] = $headsup_view; $content[] = $headsup_actions; $content[] = $property_list; } $query = new PhabricatorAuditQuery(); $query->withCommitPHIDs(array($commit->getPHID())); $audit_requests = $query->execute(); $this->auditAuthorityPHIDs = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user); $content[] = $this->buildAuditTable($commit, $audit_requests); $content[] = $this->buildComments($commit); + $hard_limit = 1000; + $change_query = DiffusionPathChangeQuery::newFromDiffusionRequest( $drequest); + $change_query->setLimit($hard_limit + 1); $changes = $change_query->loadChanges(); + $was_limited = (count($changes) > $hard_limit); + if ($was_limited) { + $changes = array_slice($changes, 0, $hard_limit); + } + $content[] = $this->buildMergesTable($commit); $owners_paths = array(); if ($this->highlightedAudits) { $packages = id(new PhabricatorOwnersPackage())->loadAllWhere( 'phid IN (%Ls)', mpull($this->highlightedAudits, 'getAuditorPHID')); if ($packages) { $owners_paths = id(new PhabricatorOwnersPath())->loadAllWhere( 'repositoryPHID = %s AND packageID IN (%Ld)', $repository->getPHID(), mpull($packages, 'getID')); } } $change_table = new DiffusionCommitChangeTableView(); $change_table->setDiffusionRequest($drequest); $change_table->setPathChanges($changes); $change_table->setOwnersPaths($owners_paths); $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()); } - $pane_id = null; if ($bad_commit) { $error_panel = new AphrontErrorView(); $error_panel->setTitle('Bad Commit'); $error_panel->appendChild( phutil_escape_html($bad_commit['description'])); $content[] = $error_panel; } else if ($is_foreign) { // Don't render anything else. } else if (!count($changes)) { $no_changes = new AphrontErrorView(); $no_changes->setSeverity(AphrontErrorView::SEVERITY_WARNING); $no_changes->setTitle('Not Yet Parsed'); // TODO: This can also happen with weird SVN changes that don't do // anything (or only alter properties?), although the real no-changes case // is extremely rare and might be impossible to produce organically. We // should probably write some kind of "Nothing Happened!" change into the // DB once we parse these changes so we can distinguish between // "not parsed yet" and "no changes". $no_changes->appendChild( "This commit hasn't been fully parsed yet (or doesn't affect any ". "paths)."); $content[] = $no_changes; + } else if ($was_limited) { + $huge_commit = new AphrontErrorView(); + $huge_commit->setSeverity(AphrontErrorView::SEVERITY_WARNING); + $huge_commit->setTitle(pht('Enormous Commit')); + $huge_commit->appendChild( + pht( + 'This commit is enormous, and affects more than %d files. '. + 'Changes are not shown.', + $hard_limit)); + $content[] = $huge_commit; } else { $change_panel = new AphrontPanelView(); $change_panel->setHeader("Changes (".number_format($count).")"); $change_panel->setID('toc'); - if ($count > self::CHANGES_LIMIT) { $show_all_button = phutil_tag( 'a', array( 'class' => 'button green', 'href' => '?show_all=true', ), 'Show All Changes'); $warning_view = id(new AphrontErrorView()) ->setSeverity(AphrontErrorView::SEVERITY_WARNING) ->setTitle('Very Large Commit') ->appendChild( "

This commit is very large. Load each file individually.

"); $change_panel->appendChild($warning_view); $change_panel->addButton($show_all_button); } $change_panel->appendChild($change_table); $change_panel->setNoBackground(); $content[] = $change_panel; $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: case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: $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; } } $references[$key] = $drequest->generateURI( array( 'action' => 'rendering-ref', 'path' => $changeset->getFilename(), )); } // TODO: Some parts of the views still rely on properties of the // DifferentialChangeset. Make the objects ephemeral to make sure we don't // accidentally save them, and then set their ID to the appropriate ID for // this application (the path IDs). $path_ids = array_flip(mpull($changes, 'getPath')); foreach ($changesets as $changeset) { $changeset->makeEphemeral(); $changeset->setID($path_ids[$changeset->getFilename()]); } if ($count <= self::CHANGES_LIMIT) { $visible_changesets = $changesets; } else { $visible_changesets = array(); $inlines = id(new PhabricatorAuditInlineComment())->loadAllWhere( 'commitPHID = %s AND (auditCommentID IS NOT NULL OR authorPHID = %s)', $commit->getPHID(), $user->getPHID()); $path_ids = mpull($inlines, null, 'getPathID'); foreach ($changesets as $key => $changeset) { if (array_key_exists($changeset->getID(), $path_ids)) { $visible_changesets[$key] = $changeset; } } } $change_list_title = DiffusionView::nameCommit( $repository, $commit->getCommitIdentifier() ); $change_list = new DifferentialChangesetListView(); $change_list->setTitle($change_list_title); $change_list->setChangesets($changesets); $change_list->setVisibleChangesets($visible_changesets); $change_list->setRenderingReferences($references); $change_list->setRenderURI('/diffusion/'.$callsign.'/diff/'); $change_list->setRepository($repository); $change_list->setUser($user); // pick the first branch for "Browse in Diffusion" View Option $branches = $commit_data->getCommitDetail('seenOnBranches', array()); $first_branch = reset($branches); $change_list->setBranch($first_branch); $change_list->setStandaloneURI( '/diffusion/'.$callsign.'/diff/'); $change_list->setRawFileURIs( // TODO: Implement this, somewhat tricky if there's an octopus merge // or whatever? null, '/diffusion/'.$callsign.'/diff/?view=r'); $change_list->setInlineCommentControllerURI( '/diffusion/inline/edit/'.phutil_escape_uri($commit->getPHID()).'/'); $change_references = array(); foreach ($changesets as $key => $changeset) { $change_references[$changeset->getID()] = $references[$key]; } $change_table->setRenderingReferences($change_references); - // TODO: This is pretty awkward, unify the CSS between Diffusion and - // Differential better. - require_celerity_resource('differential-core-view-css'); - $pane_id = celerity_generate_unique_node_id(); - $add_comment_view = $this->renderAddCommentPanel($commit, - $audit_requests, - $pane_id); - $main_pane = phutil_render_tag( - 'div', - array( - 'id' => $pane_id - ), - $change_list->render(). - id(new PhabricatorAnchorView()) - ->setAnchorName('comment') - ->setNavigationMarker(true) - ->render(). - $add_comment_view); - - $content[] = $main_pane; + $content[] = $change_list->render(); } + $content[] = $this->renderAddCommentPanel($commit, $audit_requests); + $commit_id = 'r'.$callsign.$commit->getCommitIdentifier(); $short_name = DiffusionView::nameCommit( $repository, $commit->getCommitIdentifier() ); $crumbs = $this->buildCrumbs(array( 'commit' => true, )); if ($changesets) { $nav = id(new DifferentialChangesetFileTreeSideNavBuilder()) ->setAnchorName('top') ->setTitle($short_name) ->setBaseURI(new PhutilURI('/'.$commit_id)) ->build($changesets) ->setCrumbs($crumbs) ->appendChild($content); $content = $nav; } else { $content = array($crumbs, $content); } return $this->buildApplicationPage( $content, array( 'title' => $commit_id ) ); } private function loadCommitProperties( PhabricatorRepositoryCommit $commit, PhabricatorRepositoryCommitData $data, array $parents) { assert_instances_of($parents, 'PhabricatorRepositoryCommit'); $user = $this->getRequest()->getUser(); $commit_phid = $commit->getPHID(); $edges = id(new PhabricatorEdgeQuery()) ->withSourcePHIDs(array($commit_phid)) ->withEdgeTypes(array( PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK, PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT )) ->execute(); $task_phids = array_keys( $edges[$commit_phid][PhabricatorEdgeConfig::TYPE_COMMIT_HAS_TASK] ); $proj_phids = array_keys( $edges[$commit_phid][PhabricatorEdgeConfig::TYPE_COMMIT_HAS_PROJECT] ); $phids = array_merge($task_phids, $proj_phids); if ($data->getCommitDetail('authorPHID')) { $phids[] = $data->getCommitDetail('authorPHID'); } if ($data->getCommitDetail('reviewerPHID')) { $phids[] = $data->getCommitDetail('reviewerPHID'); } if ($data->getCommitDetail('committerPHID')) { $phids[] = $data->getCommitDetail('committerPHID'); } if ($data->getCommitDetail('differential.revisionPHID')) { $phids[] = $data->getCommitDetail('differential.revisionPHID'); } if ($parents) { foreach ($parents as $parent) { $phids[] = $parent->getPHID(); } } $handles = array(); if ($phids) { $handles = $this->loadViewerHandles($phids); } $props = array(); if ($commit->getAuditStatus()) { $status = PhabricatorAuditCommitStatusConstants::getStatusName( $commit->getAuditStatus()); $props['Status'] = phutil_tag( 'strong', array(), $status); } $props['Committed'] = phabricator_datetime($commit->getEpoch(), $user); $author_phid = $data->getCommitDetail('authorPHID'); if ($data->getCommitDetail('authorPHID')) { $props['Author'] = $handles[$author_phid]->renderLink(); } else { $props['Author'] = $data->getAuthorName(); } $reviewer_phid = $data->getCommitDetail('reviewerPHID'); if ($reviewer_phid) { $props['Reviewer'] = $handles[$reviewer_phid]->renderLink(); } $committer = $data->getCommitDetail('committer'); if ($committer) { $committer_phid = $data->getCommitDetail('committerPHID'); if ($data->getCommitDetail('committerPHID')) { $props['Committer'] = $handles[$committer_phid]->renderLink(); } else { $props['Committer'] = $committer; } } $revision_phid = $data->getCommitDetail('differential.revisionPHID'); if ($revision_phid) { $props['Differential Revision'] = $handles[$revision_phid]->renderLink(); } if ($parents) { $parent_links = array(); foreach ($parents as $parent) { $parent_links[] = $handles[$parent->getPHID()]->renderLink(); } $props['Parents'] = array_interleave( " \xC2\xB7 ", $parent_links); } $request = $this->getDiffusionRequest(); $props['Branches'] = phutil_tag( 'span', array( 'id' => 'commit-branches', ), 'Unknown'); $props['Tags'] = phutil_tag( 'span', array( 'id' => 'commit-tags', ), 'Unknown'); $callsign = $request->getRepository()->getCallsign(); $root = '/diffusion/'.$callsign.'/commit/'.$commit->getCommitIdentifier(); Javelin::initBehavior( 'diffusion-commit-branches', array( $root.'/branches/' => 'commit-branches', $root.'/tags/' => 'commit-tags', )); $refs = $this->buildRefs($request); if ($refs) { $props['References'] = $refs; } if ($task_phids) { $task_list = array(); foreach ($task_phids as $phid) { $task_list[] = $handles[$phid]->renderLink(); } $task_list = array_interleave(phutil_tag('br'), $task_list); $props['Tasks'] = $task_list; } if ($proj_phids) { $proj_list = array(); foreach ($proj_phids as $phid) { $proj_list[] = $handles[$phid]->renderLink(); } $proj_list = array_interleave(phutil_tag('br'), $proj_list); $props['Projects'] = $proj_list; } return $props; } private function buildAuditTable( PhabricatorRepositoryCommit $commit, array $audits) { assert_instances_of($audits, 'PhabricatorRepositoryAuditRequest'); $user = $this->getRequest()->getUser(); $view = new PhabricatorAuditListView(); $view->setAudits($audits); $view->setCommits(array($commit)); $view->setUser($user); $view->setShowDescriptions(false); $phids = $view->getRequiredHandlePHIDs(); $handles = $this->loadViewerHandles($phids); $view->setHandles($handles); $view->setAuthorityPHIDs($this->auditAuthorityPHIDs); $this->highlightedAudits = $view->getHighlightedAudits(); $panel = new AphrontPanelView(); $panel->setHeader('Audits'); $panel->setCaption('Audits you are responsible for are highlighted.'); $panel->appendChild($view); $panel->setNoBackground(); return $panel; } private function buildComments(PhabricatorRepositoryCommit $commit) { $user = $this->getRequest()->getUser(); $comments = id(new PhabricatorAuditComment())->loadAllWhere( 'targetPHID = %s ORDER BY dateCreated ASC', $commit->getPHID()); $inlines = id(new PhabricatorAuditInlineComment())->loadAllWhere( 'commitPHID = %s AND auditCommentID IS NOT NULL', $commit->getPHID()); $path_ids = mpull($inlines, 'getPathID'); $path_map = array(); if ($path_ids) { $path_map = id(new DiffusionPathQuery()) ->withPathIDs($path_ids) ->execute(); $path_map = ipull($path_map, 'path', 'id'); } $engine = new PhabricatorMarkupEngine(); $engine->setViewer($user); foreach ($comments as $comment) { $engine->addObject( $comment, PhabricatorAuditComment::MARKUP_FIELD_BODY); } foreach ($inlines as $inline) { $engine->addObject( $inline, PhabricatorInlineCommentInterface::MARKUP_FIELD_BODY); } $engine->process(); $view = new DiffusionCommentListView(); $view->setMarkupEngine($engine); $view->setUser($user); $view->setComments($comments); $view->setInlineComments($inlines); $view->setPathMap($path_map); $phids = $view->getRequiredHandlePHIDs(); $handles = $this->loadViewerHandles($phids); $view->setHandles($handles); return $view; } private function renderAddCommentPanel( PhabricatorRepositoryCommit $commit, - array $audit_requests, - $pane_id = null) { + array $audit_requests) { assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest'); $user = $this->getRequest()->getUser(); $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business'); + $pane_id = celerity_generate_unique_node_id(); Javelin::initBehavior( 'differential-keyboard-navigation', array( 'haunt' => $pane_id, )); $draft = id(new PhabricatorDraft())->loadOneWhere( 'authorPHID = %s AND draftKey = %s', $user->getPHID(), 'diffusion-audit-'.$commit->getID()); if ($draft) { $draft = $draft->getDraft(); } else { $draft = null; } $actions = $this->getAuditActions($commit, $audit_requests); $form = id(new AphrontFormView()) ->setUser($user) ->setAction('/audit/addcomment/') ->addHiddenInput('commit', $commit->getPHID()) ->appendChild( id(new AphrontFormSelectControl()) ->setLabel('Action') ->setName('action') ->setID('audit-action') ->setOptions($actions)) ->appendChild( id(new AphrontFormTokenizerControl()) ->setLabel('Add Auditors') ->setName('auditors') ->setControlID('add-auditors') ->setControlStyle('display: none') ->setID('add-auditors-tokenizer') ->setDisableBehavior(true)) ->appendChild( id(new AphrontFormTokenizerControl()) ->setLabel('Add CCs') ->setName('ccs') ->setControlID('add-ccs') ->setControlStyle('display: none') ->setID('add-ccs-tokenizer') ->setDisableBehavior(true)) ->appendChild( id(new PhabricatorRemarkupControl()) ->setLabel('Comments') ->setName('content') ->setValue($draft) ->setID('audit-content') ->setUser($user)) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue($is_serious ? 'Submit' : 'Cook the Books')); $panel = new AphrontPanelView(); $panel->setHeader($is_serious ? 'Audit Commit' : 'Creative Accounting'); $panel->appendChild($form); $panel->addClass('aphront-panel-accent'); $panel->addClass('aphront-panel-flush'); require_celerity_resource('phabricator-transaction-view-css'); Javelin::initBehavior( 'differential-add-reviewers-and-ccs', array( 'dynamic' => array( 'add-auditors-tokenizer' => array( 'actions' => array('add_auditors' => 1), 'src' => '/typeahead/common/users/', 'row' => 'add-auditors', 'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'), 'placeholder' => 'Type a user name...', ), 'add-ccs-tokenizer' => array( 'actions' => array('add_ccs' => 1), 'src' => '/typeahead/common/mailable/', 'row' => 'add-ccs', 'ondemand' => PhabricatorEnv::getEnvConfig('tokenizer.ondemand'), 'placeholder' => 'Type a user or mailing list...', ), ), 'select' => 'audit-action', )); Javelin::initBehavior('differential-feedback-preview', array( 'uri' => '/audit/preview/'.$commit->getID().'/', 'preview' => 'audit-preview', 'content' => 'audit-content', 'action' => 'audit-action', 'previewTokenizers' => array( 'auditors' => 'add-auditors-tokenizer', 'ccs' => 'add-ccs-tokenizer', ), 'inline' => 'inline-comment-preview', 'inlineuri' => '/diffusion/inline/preview/'.$commit->getPHID().'/', )); $preview_panel = '
Loading preview...
'; - return + // TODO: This is pretty awkward, unify the CSS between Diffusion and + // Differential better. + require_celerity_resource('differential-core-view-css'); + + return phutil_render_tag( + 'div', + array( + 'id' => $pane_id, + ), phutil_render_tag( 'div', array( 'class' => 'differential-add-comment-panel', ), + id(new PhabricatorAnchorView()) + ->setAnchorName('comment') + ->setNavigationMarker(true) + ->render(). $panel->render(). - $preview_panel); + $preview_panel)); } /** * Return a map of available audit actions for rendering into a