Page MenuHomestyx hydra

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/conf/default.conf.php b/conf/default.conf.php
index 26f76dd3ce..b22e053827 100644
--- a/conf/default.conf.php
+++ b/conf/default.conf.php
@@ -1,1337 +1,1326 @@
<?php
// IMPORTANT: DO NOT EDIT THIS FILE.
// This file is no longer read by default, and your efforts will have no effect.
// Follow the instructions in the documentation to configure Phabricator.
return array(
// The root URI which Phabricator is installed on.
// Example: "http://phabricator.example.com/"
'phabricator.base-uri' => 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 <gwashington@example.com>'
// - 'real' - 'George Washington <gwashington@example.com>'
// - 'full' - 'gwashington (George Washington) <gwashington@example.com>'
// 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,
// 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, and generally make development easier. 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 <img /> 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
- // <gwashinton@example.com>" 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 <N> 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',
// 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/resources/ircbot/example_config.json b/resources/ircbot/example_config.json
index 0e246ce536..6dadec2952 100644
--- a/resources/ircbot/example_config.json
+++ b/resources/ircbot/example_config.json
@@ -1,27 +1,27 @@
{
"server" : "irc.freenode.net",
"port" : 6667,
"nick" : "phabot",
"join" : [
"#phabot-test"
],
"handlers" : [
"PhabricatorIRCProtocolHandler",
- "PhabricatorIRCObjectNameHandler",
- "PhabricatorIRCSymbolHandler",
- "PhabricatorIRCLogHandler",
- "PhabricatorIRCWhatsNewHandler",
- "PhabricatorIRCDifferentialNotificationHandler",
- "PhabricatorIRCMacroHandler"
+ "PhabricatorBotObjectNameHandler",
+ "PhabricatorBotSymbolHandler",
+ "PhabricatorBotLogHandler",
+ "PhabricatorBotWhatsNewHandler",
+ "PhabricatorBotDifferentialNotificationHandler",
+ "PhabricatorBotMacroHandler"
],
"conduit.uri" : null,
"conduit.user" : null,
"conduit.cert" : null,
"macro.size" : 48,
"macro.sleep" : 0.25,
"macro.aspect" : 0.66,
"notification.channels" : ["#phabot-test"]
}
diff --git a/resources/sql/patches/20130131.conpherencepics.sql b/resources/sql/patches/20130131.conpherencepics.sql
new file mode 100644
index 0000000000..421291225f
--- /dev/null
+++ b/resources/sql/patches/20130131.conpherencepics.sql
@@ -0,0 +1,6 @@
+ALTER TABLE {$NAMESPACE}_conpherence.conpherence_thread
+ DROP imagePHID,
+ ADD imagePHIDs LONGTEXT COLLATE utf8_bin NOT NULL AFTER title;
+
+UPDATE {$NAMESPACE}_conpherence.conpherence_thread
+ SET imagePHIDs = '{}' WHERE imagePHIDs = '';
diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
index 4d694646f7..9ba4da8503 100644
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -1,3728 +1,3771 @@
<?php
/**
* This file is automatically generated. Use 'celerity_mapper.php' to rebuild
* it.
* @generated
*/
celerity_register_resource_map(array(
'/rsrc/image/actions/edit.png' =>
array(
'hash' => 'ae90914d120ac3838ddc633b480343f3',
'uri' => '/res/ae90914d/rsrc/image/actions/edit.png',
'disk' => '/rsrc/image/actions/edit.png',
'type' => 'png',
),
'/rsrc/image/avatar.png' =>
array(
'hash' => '1c5f255071537f05406adee86717ff27',
'uri' => '/res/1c5f2550/rsrc/image/avatar.png',
'disk' => '/rsrc/image/avatar.png',
'type' => 'png',
),
'/rsrc/image/checker_dark.png' =>
array(
'hash' => '640f795343df76ebe5409aae6187e57f',
'uri' => '/res/640f7953/rsrc/image/checker_dark.png',
'disk' => '/rsrc/image/checker_dark.png',
'type' => 'png',
),
'/rsrc/image/checker_light.png' =>
array(
'hash' => '7f8f3ef8beb0f2cc4cc69efb9e1c3308',
'uri' => '/res/7f8f3ef8/rsrc/image/checker_light.png',
'disk' => '/rsrc/image/checker_light.png',
'type' => 'png',
),
'/rsrc/image/credit_cards.png' =>
array(
'hash' => '681448de424ea159b6ea68af04c046ae',
'uri' => '/res/681448de/rsrc/image/credit_cards.png',
'disk' => '/rsrc/image/credit_cards.png',
'type' => 'png',
),
'/rsrc/image/darkload.gif' =>
array(
'hash' => '3a52cb7145d6e70f461fed21273117f2',
'uri' => '/res/3a52cb71/rsrc/image/darkload.gif',
'disk' => '/rsrc/image/darkload.gif',
'type' => 'gif',
),
'/rsrc/image/divot.png' =>
array(
'hash' => '3be267bd11ea375bf68e808893718e0e',
'uri' => '/res/3be267bd/rsrc/image/divot.png',
'disk' => '/rsrc/image/divot.png',
'type' => 'png',
),
'/rsrc/image/grippy_texture.png' =>
array(
'hash' => 'a8945e12ceeaddd5b491a8d81cfa19c1',
'uri' => '/res/a8945e12/rsrc/image/grippy_texture.png',
'disk' => '/rsrc/image/grippy_texture.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/arrow_branch.png' =>
array(
'hash' => 'f27b67520766e3d971722bcff703f3a8',
'uri' => '/res/f27b6752/rsrc/image/icon/fatcow/arrow_branch.png',
'disk' => '/rsrc/image/icon/fatcow/arrow_branch.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/arrow_merge.png' =>
array(
'hash' => 'c4bd97f3b1257439e2123ef69d2194d0',
'uri' => '/res/c4bd97f3/rsrc/image/icon/fatcow/arrow_merge.png',
'disk' => '/rsrc/image/icon/fatcow/arrow_merge.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/bullet_black.png' =>
array(
'hash' => '718f9c560a13766796f1be7dfaadeeab',
'uri' => '/res/718f9c56/rsrc/image/icon/fatcow/bullet_black.png',
'disk' => '/rsrc/image/icon/fatcow/bullet_black.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/bullet_orange.png' =>
array(
'hash' => 'c3bf91b65baacb27f2af143ab9180119',
'uri' => '/res/c3bf91b6/rsrc/image/icon/fatcow/bullet_orange.png',
'disk' => '/rsrc/image/icon/fatcow/bullet_orange.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/bullet_red.png' =>
array(
'hash' => '00273e4aa6ea3de630295610d6c9560c',
'uri' => '/res/00273e4a/rsrc/image/icon/fatcow/bullet_red.png',
'disk' => '/rsrc/image/icon/fatcow/bullet_red.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/calendar_edit.png' =>
array(
'hash' => 'de249c0f4f37bf5b2c69ff39ec5573fb',
'uri' => '/res/de249c0f/rsrc/image/icon/fatcow/calendar_edit.png',
'disk' => '/rsrc/image/icon/fatcow/calendar_edit.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/document_black.png' =>
array(
'hash' => '44d65a7f05a9c921719deedc160d68f7',
'uri' => '/res/44d65a7f/rsrc/image/icon/fatcow/document_black.png',
'disk' => '/rsrc/image/icon/fatcow/document_black.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/flag_blue.png' =>
array(
'hash' => '75a080492f900fbe489e4b27e403962b',
'uri' => '/res/75a08049/rsrc/image/icon/fatcow/flag_blue.png',
'disk' => '/rsrc/image/icon/fatcow/flag_blue.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/flag_finish.png' =>
array(
'hash' => '4af11fc7fab8e4610cbc3c88a02d4f78',
'uri' => '/res/4af11fc7/rsrc/image/icon/fatcow/flag_finish.png',
'disk' => '/rsrc/image/icon/fatcow/flag_finish.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/flag_ghost.png' =>
array(
'hash' => '14c9f30a37b43f276f27a27a924bf02d',
'uri' => '/res/14c9f30a/rsrc/image/icon/fatcow/flag_ghost.png',
'disk' => '/rsrc/image/icon/fatcow/flag_ghost.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/flag_green.png' =>
array(
'hash' => 'fed01374cd396cb774872762dcc447e1',
'uri' => '/res/fed01374/rsrc/image/icon/fatcow/flag_green.png',
'disk' => '/rsrc/image/icon/fatcow/flag_green.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/flag_orange.png' =>
array(
'hash' => '88008cb8bb99761a37e5a743e2455aeb',
'uri' => '/res/88008cb8/rsrc/image/icon/fatcow/flag_orange.png',
'disk' => '/rsrc/image/icon/fatcow/flag_orange.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/flag_pink.png' =>
array(
'hash' => '2f199f06ffc3dfc81b7561a057e0bc33',
'uri' => '/res/2f199f06/rsrc/image/icon/fatcow/flag_pink.png',
'disk' => '/rsrc/image/icon/fatcow/flag_pink.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/flag_purple.png' =>
array(
'hash' => '16358629dc86c39550b575586eb5df80',
'uri' => '/res/16358629/rsrc/image/icon/fatcow/flag_purple.png',
'disk' => '/rsrc/image/icon/fatcow/flag_purple.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/flag_red.png' =>
array(
'hash' => '210c28b4d93c439a499f5814f5e05772',
'uri' => '/res/210c28b4/rsrc/image/icon/fatcow/flag_red.png',
'disk' => '/rsrc/image/icon/fatcow/flag_red.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/flag_yellow.png' =>
array(
'hash' => 'bdfd73744a80bb80329ae50bc8a5f962',
'uri' => '/res/bdfd7374/rsrc/image/icon/fatcow/flag_yellow.png',
'disk' => '/rsrc/image/icon/fatcow/flag_yellow.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/folder.png' =>
array(
'hash' => '25e46cf9d210dde2242332296f79938c',
'uri' => '/res/25e46cf9/rsrc/image/icon/fatcow/folder.png',
'disk' => '/rsrc/image/icon/fatcow/folder.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/folder_go.png' =>
array(
'hash' => 'ba922ff7959309f51a14cb7ed5124d8b',
'uri' => '/res/ba922ff7/rsrc/image/icon/fatcow/folder_go.png',
'disk' => '/rsrc/image/icon/fatcow/folder_go.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/key_question.png' =>
array(
'hash' => '530a6448a4b91edec091a9292ccfd3d9',
'uri' => '/res/530a6448/rsrc/image/icon/fatcow/key_question.png',
'disk' => '/rsrc/image/icon/fatcow/key_question.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/link.png' =>
array(
'hash' => 'be1bea49b216548433014f3324902928',
'uri' => '/res/be1bea49/rsrc/image/icon/fatcow/link.png',
'disk' => '/rsrc/image/icon/fatcow/link.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/page_white_edit.png' =>
array(
'hash' => 'e7b7e7f2d9730bc80bc5c9eac1f3e36d',
'uri' => '/res/e7b7e7f2/rsrc/image/icon/fatcow/page_white_edit.png',
'disk' => '/rsrc/image/icon/fatcow/page_white_edit.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/page_white_link.png' =>
array(
'hash' => '1cfbad14412bda6c6f132dcc7c8725fd',
'uri' => '/res/1cfbad14/rsrc/image/icon/fatcow/page_white_link.png',
'disk' => '/rsrc/image/icon/fatcow/page_white_link.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/page_white_put.png' =>
array(
'hash' => 'bb7308aa5ac40137a8262da395a267fd',
'uri' => '/res/bb7308aa/rsrc/image/icon/fatcow/page_white_put.png',
'disk' => '/rsrc/image/icon/fatcow/page_white_put.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/page_white_text.png' =>
array(
'hash' => 'e47d590b626f617fb7d1d44e96e8fd11',
'uri' => '/res/e47d590b/rsrc/image/icon/fatcow/page_white_text.png',
'disk' => '/rsrc/image/icon/fatcow/page_white_text.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/source/conduit.png' =>
array(
'hash' => '1cae0656580aa3cd0b54b9d98306b1b9',
'uri' => '/res/1cae0656/rsrc/image/icon/fatcow/source/conduit.png',
'disk' => '/rsrc/image/icon/fatcow/source/conduit.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/source/email.png' =>
array(
'hash' => '93bdb3e168da1ed68f50c42125729d4e',
'uri' => '/res/93bdb3e1/rsrc/image/icon/fatcow/source/email.png',
'disk' => '/rsrc/image/icon/fatcow/source/email.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/source/fax.png' =>
array(
'hash' => 'd7dedf229841f2d041b347afd881596f',
'uri' => '/res/d7dedf22/rsrc/image/icon/fatcow/source/fax.png',
'disk' => '/rsrc/image/icon/fatcow/source/fax.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/source/mobile.png' =>
array(
'hash' => '786e7146d1e7d7318baf76c9d2baad97',
'uri' => '/res/786e7146/rsrc/image/icon/fatcow/source/mobile.png',
'disk' => '/rsrc/image/icon/fatcow/source/mobile.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/source/tablet.png' =>
array(
'hash' => '374cd40e4965be6b2fbdef4059d0ca05',
'uri' => '/res/374cd40e/rsrc/image/icon/fatcow/source/tablet.png',
'disk' => '/rsrc/image/icon/fatcow/source/tablet.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/source/web.png' =>
array(
'hash' => 'f4882a8f5619ba505ca033f72a340635',
'uri' => '/res/f4882a8f/rsrc/image/icon/fatcow/source/web.png',
'disk' => '/rsrc/image/icon/fatcow/source/web.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/thumbnails/default160x120.png' =>
array(
'hash' => '1b52ebd1fe0eee3ed0abfc382991b265',
'uri' => '/res/1b52ebd1/rsrc/image/icon/fatcow/thumbnails/default160x120.png',
'disk' => '/rsrc/image/icon/fatcow/thumbnails/default160x120.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/thumbnails/default60x45.png' =>
array(
'hash' => '048d851d8d1daad4754e891e734c1899',
'uri' => '/res/048d851d/rsrc/image/icon/fatcow/thumbnails/default60x45.png',
'disk' => '/rsrc/image/icon/fatcow/thumbnails/default60x45.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/thumbnails/image160x120.png' =>
array(
'hash' => '434acbd8dbbc2da9f09f6205a396eba1',
'uri' => '/res/434acbd8/rsrc/image/icon/fatcow/thumbnails/image160x120.png',
'disk' => '/rsrc/image/icon/fatcow/thumbnails/image160x120.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/thumbnails/image60x45.png' =>
array(
'hash' => '29f7872dc53588fe0b8f0b330c7ee23a',
'uri' => '/res/29f7872d/rsrc/image/icon/fatcow/thumbnails/image60x45.png',
'disk' => '/rsrc/image/icon/fatcow/thumbnails/image60x45.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/thumbnails/pdf160x120.png' =>
array(
'hash' => '39d2e22541658a3472ba41ae2fa548e5',
'uri' => '/res/39d2e225/rsrc/image/icon/fatcow/thumbnails/pdf160x120.png',
'disk' => '/rsrc/image/icon/fatcow/thumbnails/pdf160x120.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/thumbnails/pdf60x45.png' =>
array(
'hash' => 'b3572e9317cbed5184d12bdfabed2727',
'uri' => '/res/b3572e93/rsrc/image/icon/fatcow/thumbnails/pdf60x45.png',
'disk' => '/rsrc/image/icon/fatcow/thumbnails/pdf60x45.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/thumbnails/zip160x120.png' =>
array(
'hash' => 'e505108688a903b5cfb674707a289bcc',
'uri' => '/res/e5051086/rsrc/image/icon/fatcow/thumbnails/zip160x120.png',
'disk' => '/rsrc/image/icon/fatcow/thumbnails/zip160x120.png',
'type' => 'png',
),
'/rsrc/image/icon/fatcow/thumbnails/zip60x45.png' =>
array(
'hash' => 'f00716f4e8f7a95e70d43504f06be0a6',
'uri' => '/res/f00716f4/rsrc/image/icon/fatcow/thumbnails/zip60x45.png',
'disk' => '/rsrc/image/icon/fatcow/thumbnails/zip60x45.png',
'type' => 'png',
),
'/rsrc/image/icon/lightbox/close-2.png' =>
array(
'hash' => '72ff3ddcc1ed5d19a715ed6242114b53',
'uri' => '/res/72ff3ddc/rsrc/image/icon/lightbox/close-2.png',
'disk' => '/rsrc/image/icon/lightbox/close-2.png',
'type' => 'png',
),
'/rsrc/image/icon/lightbox/close-hover-2.png' =>
array(
'hash' => '6ad4bd4a7820547a1d9041752546ba16',
'uri' => '/res/6ad4bd4a/rsrc/image/icon/lightbox/close-hover-2.png',
'disk' => '/rsrc/image/icon/lightbox/close-hover-2.png',
'type' => 'png',
),
'/rsrc/image/icon/lightbox/left-arrow-2.png' =>
array(
'hash' => 'd84cbb0d42739f87b8f25b2f1d2f1153',
'uri' => '/res/d84cbb0d/rsrc/image/icon/lightbox/left-arrow-2.png',
'disk' => '/rsrc/image/icon/lightbox/left-arrow-2.png',
'type' => 'png',
),
'/rsrc/image/icon/lightbox/left-arrow-hover-2.png' =>
array(
'hash' => 'cdf05f98fff3f390cd8df0c89894a3e1',
'uri' => '/res/cdf05f98/rsrc/image/icon/lightbox/left-arrow-hover-2.png',
'disk' => '/rsrc/image/icon/lightbox/left-arrow-hover-2.png',
'type' => 'png',
),
'/rsrc/image/icon/lightbox/right-arrow-2.png' =>
array(
'hash' => '52021038cb6995c71f62a804bc2d420d',
'uri' => '/res/52021038/rsrc/image/icon/lightbox/right-arrow-2.png',
'disk' => '/rsrc/image/icon/lightbox/right-arrow-2.png',
'type' => 'png',
),
'/rsrc/image/icon/lightbox/right-arrow-hover-2.png' =>
array(
'hash' => '65d5756b7b9cfcdeb2eb197a9aa6bbd2',
'uri' => '/res/65d5756b/rsrc/image/icon/lightbox/right-arrow-hover-2.png',
'disk' => '/rsrc/image/icon/lightbox/right-arrow-hover-2.png',
'type' => 'png',
),
'/rsrc/image/icon/subscribe.png' =>
array(
'hash' => '5f47a4b17de245af39a4e7a097e40623',
'uri' => '/res/5f47a4b1/rsrc/image/icon/subscribe.png',
'disk' => '/rsrc/image/icon/subscribe.png',
'type' => 'png',
),
'/rsrc/image/icon/tango/attachment.png' =>
array(
'hash' => '776fed2de89803fd8a0ba4b9deede230',
'uri' => '/res/776fed2d/rsrc/image/icon/tango/attachment.png',
'disk' => '/rsrc/image/icon/tango/attachment.png',
'type' => 'png',
),
'/rsrc/image/icon/tango/edit.png' =>
array(
'hash' => 'c0028d99dcf4e9559bbf3c88ce2d8a8d',
'uri' => '/res/c0028d99/rsrc/image/icon/tango/edit.png',
'disk' => '/rsrc/image/icon/tango/edit.png',
'type' => 'png',
),
'/rsrc/image/icon/tango/go-down.png' =>
array(
'hash' => '96862812cbb0445573c264dc057b8300',
'uri' => '/res/96862812/rsrc/image/icon/tango/go-down.png',
'disk' => '/rsrc/image/icon/tango/go-down.png',
'type' => 'png',
),
'/rsrc/image/icon/tango/log.png' =>
array(
'hash' => 'a6f72499bef279ff6807a7dbc5148f1e',
'uri' => '/res/a6f72499/rsrc/image/icon/tango/log.png',
'disk' => '/rsrc/image/icon/tango/log.png',
'type' => 'png',
),
'/rsrc/image/icon/tango/upload.png' =>
array(
'hash' => '8c11b63d6d99db3d7159c5d9a94e3062',
'uri' => '/res/8c11b63d/rsrc/image/icon/tango/upload.png',
'disk' => '/rsrc/image/icon/tango/upload.png',
'type' => 'png',
),
'/rsrc/image/icon/unsubscribe.png' =>
array(
'hash' => '29429ad65aa3af50b072b32087057361',
'uri' => '/res/29429ad6/rsrc/image/icon/unsubscribe.png',
'disk' => '/rsrc/image/icon/unsubscribe.png',
'type' => 'png',
),
'/rsrc/image/loading.gif' =>
array(
'hash' => '664297671941142f37d8c89e717ff2ce',
'uri' => '/res/66429767/rsrc/image/loading.gif',
'disk' => '/rsrc/image/loading.gif',
'type' => 'gif',
),
'/rsrc/image/main_texture.png' =>
array(
'hash' => 'e34d8143384721be73ec9b7532a977ab',
'uri' => '/res/e34d8143/rsrc/image/main_texture.png',
'disk' => '/rsrc/image/main_texture.png',
'type' => 'png',
),
'/rsrc/image/menu_texture.png' =>
array(
'hash' => 'ad020b1529b3a3b3480ca9de1d5f1e40',
'uri' => '/res/ad020b15/rsrc/image/menu_texture.png',
'disk' => '/rsrc/image/menu_texture.png',
'type' => 'png',
),
'/rsrc/image/search.png' =>
array(
'hash' => 'ff7da044e6f923b8f569dec11f97e5e5',
'uri' => '/res/ff7da044/rsrc/image/search.png',
'disk' => '/rsrc/image/search.png',
'type' => 'png',
),
'/rsrc/image/sprite-apps-X2.png' =>
array(
'hash' => '361e64ded74eee1094127c7878c2c385',
'uri' => '/res/361e64de/rsrc/image/sprite-apps-X2.png',
'disk' => '/rsrc/image/sprite-apps-X2.png',
'type' => 'png',
),
'/rsrc/image/sprite-apps-large-X2.png' =>
array(
'hash' => '73507e04b4bd4d1e8e7544f7c424fc0f',
'uri' => '/res/73507e04/rsrc/image/sprite-apps-large-X2.png',
'disk' => '/rsrc/image/sprite-apps-large-X2.png',
'type' => 'png',
),
'/rsrc/image/sprite-apps-large.png' =>
array(
'hash' => '6a5aade6134954171f2f1f8507270632',
'uri' => '/res/6a5aade6/rsrc/image/sprite-apps-large.png',
'disk' => '/rsrc/image/sprite-apps-large.png',
'type' => 'png',
),
'/rsrc/image/sprite-apps-xlarge.png' =>
array(
'hash' => '992d2c278b6a22c0fa874d457a252fbd',
'uri' => '/res/992d2c27/rsrc/image/sprite-apps-xlarge.png',
'disk' => '/rsrc/image/sprite-apps-xlarge.png',
'type' => 'png',
),
'/rsrc/image/sprite-apps.png' =>
array(
'hash' => '5e76c53e9f61755e5d3e7befa9d73ae5',
'uri' => '/res/5e76c53e/rsrc/image/sprite-apps.png',
'disk' => '/rsrc/image/sprite-apps.png',
'type' => 'png',
),
'/rsrc/image/sprite-conph-X2.png' =>
array(
'hash' => '8f79b9888577dab95d6019d1b7f2a204',
'uri' => '/res/8f79b988/rsrc/image/sprite-conph-X2.png',
'disk' => '/rsrc/image/sprite-conph-X2.png',
'type' => 'png',
),
'/rsrc/image/sprite-conph.png' =>
array(
'hash' => 'a6329b4baa648b57c00de65f6758cbd2',
'uri' => '/res/a6329b4b/rsrc/image/sprite-conph.png',
'disk' => '/rsrc/image/sprite-conph.png',
'type' => 'png',
),
'/rsrc/image/sprite-gradient.png' =>
array(
'hash' => '92aebaab67dcc6baf2ea99294368d895',
'uri' => '/res/92aebaab/rsrc/image/sprite-gradient.png',
'disk' => '/rsrc/image/sprite-gradient.png',
'type' => 'png',
),
'/rsrc/image/sprite-icon-X2.png' =>
array(
'hash' => 'c9fae25bc6221922ce26517e654a18e4',
'uri' => '/res/c9fae25b/rsrc/image/sprite-icon-X2.png',
'disk' => '/rsrc/image/sprite-icon-X2.png',
'type' => 'png',
),
'/rsrc/image/sprite-icon.png' =>
array(
'hash' => 'b690ea69bf5f2abe84d0a6e9ef64b03d',
'uri' => '/res/b690ea69/rsrc/image/sprite-icon.png',
'disk' => '/rsrc/image/sprite-icon.png',
'type' => 'png',
),
'/rsrc/image/sprite-menu-X2.png' =>
array(
'hash' => 'ad544a9287ca73b9e0d3f549834701ee',
'uri' => '/res/ad544a92/rsrc/image/sprite-menu-X2.png',
'disk' => '/rsrc/image/sprite-menu-X2.png',
'type' => 'png',
),
'/rsrc/image/sprite-menu.png' =>
array(
'hash' => '8a6822c29bfa6f33db1c1b8b02b5c6d3',
'uri' => '/res/8a6822c2/rsrc/image/sprite-menu.png',
'disk' => '/rsrc/image/sprite-menu.png',
'type' => 'png',
),
'/rsrc/image/texture/dark-menu-hover.png' =>
array(
'hash' => 'a214a732644be34872e895b338b5d639',
'uri' => '/res/a214a732/rsrc/image/texture/dark-menu-hover.png',
'disk' => '/rsrc/image/texture/dark-menu-hover.png',
'type' => 'png',
),
'/rsrc/image/texture/dark-menu.png' =>
array(
'hash' => '41ee673a762cec48a154b456ad5ac204',
'uri' => '/res/41ee673a/rsrc/image/texture/dark-menu.png',
'disk' => '/rsrc/image/texture/dark-menu.png',
'type' => 'png',
),
'/rsrc/image/texture/dust_background.jpg' =>
array(
'hash' => 'c32ab9819d4af583f5609bbd3750721a',
'uri' => '/res/c32ab981/rsrc/image/texture/dust_background.jpg',
'disk' => '/rsrc/image/texture/dust_background.jpg',
'type' => 'jpg',
),
'/rsrc/image/texture/table_header.png' =>
array(
'hash' => '4ed3f56a30d3749e8f62052b9735a316',
'uri' => '/res/4ed3f56a/rsrc/image/texture/table_header.png',
'disk' => '/rsrc/image/texture/table_header.png',
'type' => 'png',
),
'/rsrc/image/texture/table_header_hover.png' =>
array(
'hash' => 'ea1f71a604e9b4859de1e25751540437',
'uri' => '/res/ea1f71a6/rsrc/image/texture/table_header_hover.png',
'disk' => '/rsrc/image/texture/table_header_hover.png',
'type' => 'png',
),
'/rsrc/image/texture/table_header_tall.png' =>
array(
'hash' => 'b05525601f78d759f1c5e47fd9c1a8aa',
'uri' => '/res/b0552560/rsrc/image/texture/table_header_tall.png',
'disk' => '/rsrc/image/texture/table_header_tall.png',
'type' => 'png',
),
'/rsrc/swf/aphlict.swf' =>
array(
'hash' => '4b9a9d83bebaf254f3790e87b45c1f92',
'uri' => '/res/4b9a9d83/rsrc/swf/aphlict.swf',
'disk' => '/rsrc/swf/aphlict.swf',
'type' => 'swf',
),
'aphront-attached-file-view-css' =>
array(
'uri' => '/res/a6ca5487/rsrc/css/aphront/attached-file-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/attached-file-view.css',
),
'aphront-calendar-view-css' =>
array(
'uri' => '/res/87d6e40d/rsrc/css/aphront/calendar-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/calendar-view.css',
),
'aphront-contextbar-view-css' =>
array(
'uri' => '/res/ecfd5ba9/rsrc/css/aphront/context-bar.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/context-bar.css',
),
'aphront-crumbs-view-css' =>
array(
'uri' => '/res/699be12a/rsrc/css/aphront/crumbs-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/crumbs-view.css',
),
'aphront-dark-console-css' =>
array(
'uri' => '/res/63841304/rsrc/css/aphront/dark-console.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/dark-console.css',
),
'aphront-dialog-view-css' =>
array(
'uri' => '/res/215b3ab1/rsrc/css/aphront/dialog-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/dialog-view.css',
),
'aphront-error-view-css' =>
array(
'uri' => '/res/5f43a7c5/rsrc/css/aphront/error-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/error-view.css',
),
'aphront-form-view-css' =>
array(
- 'uri' => '/res/1e191b83/rsrc/css/aphront/form-view.css',
+ 'uri' => '/res/ec323d34/rsrc/css/aphront/form-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/form-view.css',
),
'aphront-list-filter-view-css' =>
array(
'uri' => '/res/e783d6e1/rsrc/css/aphront/list-filter-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/list-filter-view.css',
),
'aphront-pager-view-css' =>
array(
'uri' => '/res/43fb79f0/rsrc/css/aphront/pager-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/pager-view.css',
),
'aphront-panel-view-css' =>
array(
'uri' => '/res/3d1420b3/rsrc/css/aphront/panel-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/panel-view.css',
),
'aphront-request-failure-view-css' =>
array(
'uri' => '/res/c9a43002/rsrc/css/aphront/request-failure-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/request-failure-view.css',
),
'aphront-table-view-css' =>
array(
'uri' => '/res/fd33a0f0/rsrc/css/aphront/table-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/table-view.css',
),
'aphront-tokenizer-control-css' =>
array(
'uri' => '/res/207105f0/rsrc/css/aphront/tokenizer.css',
'type' => 'css',
'requires' =>
array(
0 => 'aphront-typeahead-control-css',
),
'disk' => '/rsrc/css/aphront/tokenizer.css',
),
'aphront-tooltip-css' =>
array(
'uri' => '/res/3a7d8e07/rsrc/css/aphront/tooltip.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/tooltip.css',
),
'aphront-typeahead-control-css' =>
array(
'uri' => '/res/ef59c20c/rsrc/css/aphront/typeahead.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/typeahead.css',
),
'config-options-css' =>
array(
'uri' => '/res/e6c21f2f/rsrc/css/application/config/config-options.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/config/config-options.css',
),
'conpherence-header-pane-css' =>
array(
- 'uri' => '/res/4b8aebd2/rsrc/css/application/conpherence/header-pane.css',
+ 'uri' => '/res/11c32adc/rsrc/css/application/conpherence/header-pane.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/conpherence/header-pane.css',
),
'conpherence-menu-css' =>
array(
'uri' => '/res/0dc6b412/rsrc/css/application/conpherence/menu.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/conpherence/menu.css',
),
'conpherence-message-pane-css' =>
array(
'uri' => '/res/88b1927c/rsrc/css/application/conpherence/message-pane.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/conpherence/message-pane.css',
),
'conpherence-update-css' =>
array(
- 'uri' => '/res/8e4757b5/rsrc/css/application/conpherence/update.css',
+ 'uri' => '/res/92094ed7/rsrc/css/application/conpherence/update.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/conpherence/update.css',
),
'conpherence-widget-pane-css' =>
array(
- 'uri' => '/res/b3e6a558/rsrc/css/application/conpherence/widget-pane.css',
+ 'uri' => '/res/6e5755bb/rsrc/css/application/conpherence/widget-pane.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/conpherence/widget-pane.css',
),
'differential-changeset-view-css' =>
array(
'uri' => '/res/ea694162/rsrc/css/application/differential/changeset-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/changeset-view.css',
),
'differential-core-view-css' =>
array(
'uri' => '/res/85fe5117/rsrc/css/application/differential/core.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/core.css',
),
'differential-inline-comment-editor' =>
array(
'uri' => '/res/e0ad34ac/rsrc/js/application/differential/DifferentialInlineCommentEditor.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-dom',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-install',
4 => 'javelin-request',
5 => 'javelin-workflow',
),
'disk' => '/rsrc/js/application/differential/DifferentialInlineCommentEditor.js',
),
'differential-local-commits-view-css' =>
array(
'uri' => '/res/224f3703/rsrc/css/application/differential/local-commits-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/local-commits-view.css',
),
'differential-results-table-css' =>
array(
'uri' => '/res/aab3123c/rsrc/css/application/differential/results-table.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/results-table.css',
),
'differential-revision-add-comment-css' =>
array(
'uri' => '/res/849748d3/rsrc/css/application/differential/add-comment.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/add-comment.css',
),
'differential-revision-comment-css' =>
array(
'uri' => '/res/42c222f4/rsrc/css/application/differential/revision-comment.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/revision-comment.css',
),
'differential-revision-comment-list-css' =>
array(
'uri' => '/res/3b31faa3/rsrc/css/application/differential/revision-comment-list.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/revision-comment-list.css',
),
'differential-revision-history-css' =>
array(
'uri' => '/res/d41bc64c/rsrc/css/application/differential/revision-history.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/revision-history.css',
),
'differential-revision-list-css' =>
array(
'uri' => '/res/fe6c4721/rsrc/css/application/differential/revision-list.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/revision-list.css',
),
'differential-table-of-contents-css' =>
array(
'uri' => '/res/4fde8bfc/rsrc/css/application/differential/table-of-contents.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/differential/table-of-contents.css',
),
'diffusion-commit-view-css' =>
array(
'uri' => '/res/b445944e/rsrc/css/application/diffusion/commit-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/diffusion/commit-view.css',
),
'diffusion-icons-css' =>
array(
'uri' => '/res/b93e32c9/rsrc/css/application/diffusion/diffusion-icons.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/diffusion/diffusion-icons.css',
),
'diffusion-source-css' =>
array(
'uri' => '/res/6a28b429/rsrc/css/application/diffusion/diffusion-source.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/diffusion/diffusion-source.css',
),
'global-drag-and-drop-css' =>
array(
'uri' => '/res/4e24cb65/rsrc/css/application/files/global-drag-and-drop.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/files/global-drag-and-drop.css',
),
'herald-css' =>
array(
'uri' => '/res/2150a55d/rsrc/css/application/herald/herald.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/herald/herald.css',
),
'herald-rule-editor' =>
array(
'uri' => '/res/f35d7e23/rsrc/js/application/herald/HeraldRuleEditor.js',
'type' => 'js',
'requires' =>
array(
0 => 'multirow-row-manager',
1 => 'javelin-install',
2 => 'javelin-typeahead',
3 => 'javelin-util',
4 => 'javelin-dom',
5 => 'javelin-tokenizer',
6 => 'javelin-typeahead-preloaded-source',
7 => 'javelin-stratcom',
8 => 'javelin-json',
9 => 'phabricator-prefab',
),
'disk' => '/rsrc/js/application/herald/HeraldRuleEditor.js',
),
'herald-test-css' =>
array(
'uri' => '/res/c0cd6bdb/rsrc/css/application/herald/herald-test.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/herald/herald-test.css',
),
'inline-comment-summary-css' =>
array(
'uri' => '/res/338704f7/rsrc/css/application/diff/inline-comment-summary.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/diff/inline-comment-summary.css',
),
'javelin-aphlict' =>
array(
'uri' => '/res/c0b9e53f/rsrc/js/application/aphlict/Aphlict.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'disk' => '/rsrc/js/application/aphlict/Aphlict.js',
),
'javelin-behavior' =>
array(
'uri' => '/res/ef4eda09/rsrc/js/javelin/lib/behavior.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-magical-init',
),
'disk' => '/rsrc/js/javelin/lib/behavior.js',
),
'javelin-behavior-aphlict-dropdown' =>
array(
'uri' => '/res/2418f448/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-request',
2 => 'javelin-stratcom',
3 => 'javelin-vector',
4 => 'javelin-dom',
5 => 'javelin-uri',
),
'disk' => '/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js',
),
'javelin-behavior-aphlict-listen' =>
array(
'uri' => '/res/6dde3f43/rsrc/js/application/aphlict/behavior-aphlict-listen.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-aphlict',
2 => 'javelin-stratcom',
3 => 'javelin-request',
4 => 'javelin-uri',
5 => 'javelin-dom',
6 => 'javelin-json',
7 => 'phabricator-notification',
),
'disk' => '/rsrc/js/application/aphlict/behavior-aphlict-listen.js',
),
'javelin-behavior-aphront-basic-tokenizer' =>
array(
'uri' => '/res/cf049052/rsrc/js/application/core/behavior-tokenizer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'phabricator-prefab',
),
'disk' => '/rsrc/js/application/core/behavior-tokenizer.js',
),
+ 'javelin-behavior-aphront-crop' =>
+ array(
+ 'uri' => '/res/cda1eace/rsrc/js/application/core/behavior-crop.js',
+ 'type' => 'js',
+ 'requires' =>
+ array(
+ 0 => 'javelin-behavior',
+ 1 => 'javelin-dom',
+ 2 => 'javelin-vector',
+ 3 => 'javelin-magical-init',
+ ),
+ 'disk' => '/rsrc/js/application/core/behavior-crop.js',
+ ),
'javelin-behavior-aphront-drag-and-drop' =>
array(
'uri' => '/res/3d809b40/rsrc/js/application/core/behavior-drag-and-drop.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phabricator-file-upload',
3 => 'phabricator-drag-and-drop-file-upload',
),
'disk' => '/rsrc/js/application/core/behavior-drag-and-drop.js',
),
'javelin-behavior-aphront-drag-and-drop-textarea' =>
array(
'uri' => '/res/853e33b9/rsrc/js/application/core/behavior-drag-and-drop-textarea.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phabricator-drag-and-drop-file-upload',
3 => 'phabricator-paste-file-upload',
4 => 'phabricator-textareautils',
),
'disk' => '/rsrc/js/application/core/behavior-drag-and-drop-textarea.js',
),
'javelin-behavior-aphront-form-disable-on-submit' =>
array(
'uri' => '/res/b5052cd0/rsrc/js/application/core/behavior-form.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-form.js',
),
'javelin-behavior-aphront-more' =>
array(
'uri' => '/res/9ad83c3c/rsrc/js/application/core/behavior-more.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-more.js',
),
'javelin-behavior-audit-preview' =>
array(
'uri' => '/res/3048b073/rsrc/js/application/diffusion/behavior-audit-preview.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-shaped-request',
),
'disk' => '/rsrc/js/application/diffusion/behavior-audit-preview.js',
),
+ 'javelin-behavior-conpherence-drag-and-drop-photo' =>
+ array(
+ 'uri' => '/res/9e3eb1cd/rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js',
+ 'type' => 'js',
+ 'requires' =>
+ array(
+ 0 => 'javelin-behavior',
+ 1 => 'javelin-dom',
+ 2 => 'javelin-workflow',
+ 3 => 'phabricator-drag-and-drop-file-upload',
+ ),
+ 'disk' => '/rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js',
+ ),
'javelin-behavior-conpherence-init' =>
array(
'uri' => '/res/bd911b43/rsrc/js/application/conpherence/behavior-init.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/conpherence/behavior-init.js',
),
'javelin-behavior-conpherence-menu' =>
array(
- 'uri' => '/res/9d21fb86/rsrc/js/application/conpherence/behavior-menu.js',
+ 'uri' => '/res/986774a0/rsrc/js/application/conpherence/behavior-menu.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-workflow',
3 => 'javelin-util',
4 => 'javelin-stratcom',
5 => 'javelin-uri',
),
'disk' => '/rsrc/js/application/conpherence/behavior-menu.js',
),
'javelin-behavior-conpherence-widget-pane' =>
array(
- 'uri' => '/res/f3e0dbba/rsrc/js/application/conpherence/behavior-widget-pane.js',
+ 'uri' => '/res/4fb51b46/rsrc/js/application/conpherence/behavior-widget-pane.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/conpherence/behavior-widget-pane.js',
),
'javelin-behavior-countdown-timer' =>
array(
'uri' => '/res/7468acb7/rsrc/js/application/countdown/timer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
),
'disk' => '/rsrc/js/application/countdown/timer.js',
),
'javelin-behavior-dark-console' =>
array(
- 'uri' => '/res/52444d4e/rsrc/js/application/core/behavior-dark-console.js',
+ 'uri' => '/res/ae7f15ce/rsrc/js/application/core/behavior-dark-console.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-request',
5 => 'phabricator-keyboard-shortcut',
),
'disk' => '/rsrc/js/application/core/behavior-dark-console.js',
),
'javelin-behavior-device' =>
array(
'uri' => '/res/a10b851b/rsrc/js/application/core/behavior-device.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-vector',
4 => 'javelin-install',
),
'disk' => '/rsrc/js/application/core/behavior-device.js',
),
'javelin-behavior-differential-accept-with-errors' =>
array(
'uri' => '/res/8fea67b3/rsrc/js/application/differential/behavior-accept-with-errors.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-accept-with-errors.js',
),
'javelin-behavior-differential-add-reviewers-and-ccs' =>
array(
'uri' => '/res/27be3f81/rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phabricator-prefab',
),
'disk' => '/rsrc/js/application/differential/behavior-add-reviewers-and-ccs.js',
),
'javelin-behavior-differential-comment-jump' =>
array(
'uri' => '/res/b580229b/rsrc/js/application/differential/behavior-comment-jump.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-util',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-comment-jump.js',
),
'javelin-behavior-differential-diff-radios' =>
array(
'uri' => '/res/004cb66f/rsrc/js/application/differential/behavior-diff-radios.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-diff-radios.js',
),
'javelin-behavior-differential-dropdown-menus' =>
array(
'uri' => '/res/752f5dfc/rsrc/js/application/differential/behavior-dropdown-menus.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-stratcom',
4 => 'phabricator-dropdown-menu',
5 => 'phabricator-menu-item',
),
'disk' => '/rsrc/js/application/differential/behavior-dropdown-menus.js',
),
'javelin-behavior-differential-edit-inline-comments' =>
array(
'uri' => '/res/70c1f3a3/rsrc/js/application/differential/behavior-edit-inline-comments.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-util',
4 => 'javelin-vector',
5 => 'differential-inline-comment-editor',
),
'disk' => '/rsrc/js/application/differential/behavior-edit-inline-comments.js',
),
'javelin-behavior-differential-feedback-preview' =>
array(
'uri' => '/res/5fbce8db/rsrc/js/application/differential/behavior-comment-preview.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-request',
4 => 'javelin-util',
5 => 'phabricator-shaped-request',
),
'disk' => '/rsrc/js/application/differential/behavior-comment-preview.js',
),
'javelin-behavior-differential-keyboard-navigation' =>
array(
- 'uri' => '/res/a7798465/rsrc/js/application/differential/behavior-keyboard-nav.js',
+ 'uri' => '/res/89e93cc9/rsrc/js/application/differential/behavior-keyboard-nav.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'phabricator-keyboard-shortcut',
),
'disk' => '/rsrc/js/application/differential/behavior-keyboard-nav.js',
),
'javelin-behavior-differential-populate' =>
array(
- 'uri' => '/res/71effec4/rsrc/js/application/differential/behavior-populate.js',
+ 'uri' => '/res/526c2615/rsrc/js/application/differential/behavior-populate.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-workflow',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-stratcom',
5 => 'javelin-behavior-device',
- 6 => 'phabricator-tooltip',
+ 6 => 'javelin-vector',
+ 7 => 'phabricator-tooltip',
),
'disk' => '/rsrc/js/application/differential/behavior-populate.js',
),
'javelin-behavior-differential-show-all-comments' =>
array(
'uri' => '/res/eaa12efc/rsrc/js/application/differential/behavior-show-all-comments.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-show-all-comments.js',
),
'javelin-behavior-differential-show-field-details' =>
array(
'uri' => '/res/8d57f459/rsrc/js/application/differential/behavior-show-field-details.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-show-field-details.js',
),
'javelin-behavior-differential-show-more' =>
array(
'uri' => '/res/b9f93090/rsrc/js/application/differential/behavior-show-more.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-workflow',
3 => 'javelin-util',
4 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/differential/behavior-show-more.js',
),
'javelin-behavior-differential-toggle-files' =>
array(
'uri' => '/res/ae937207/rsrc/js/application/differential/behavior-toggle-files.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/differential/behavior-toggle-files.js',
),
'javelin-behavior-differential-user-select' =>
array(
'uri' => '/res/23c51a5d/rsrc/js/application/differential/behavior-user-select.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/differential/behavior-user-select.js',
),
'javelin-behavior-diffusion-commit-branches' =>
array(
'uri' => '/res/1ede335a/rsrc/js/application/diffusion/behavior-commit-branches.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-request',
),
'disk' => '/rsrc/js/application/diffusion/behavior-commit-branches.js',
),
'javelin-behavior-diffusion-commit-graph' =>
array(
'uri' => '/res/62bd2035/rsrc/js/application/diffusion/behavior-commit-graph.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/diffusion/behavior-commit-graph.js',
),
'javelin-behavior-diffusion-jump-to' =>
array(
'uri' => '/res/7c42e1ba/rsrc/js/application/diffusion/behavior-jump-to.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-util',
2 => 'javelin-vector',
3 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/diffusion/behavior-jump-to.js',
),
'javelin-behavior-diffusion-line-linker' =>
array(
'uri' => '/res/d3cf5499/rsrc/js/application/diffusion/behavior-line-linker.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-uri',
),
'disk' => '/rsrc/js/application/diffusion/behavior-line-linker.js',
),
'javelin-behavior-diffusion-pull-lastmodified' =>
array(
'uri' => '/res/29fe2790/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-request',
),
'disk' => '/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
),
'javelin-behavior-error-log' =>
array(
'uri' => '/res/f46289e9/rsrc/js/application/core/behavior-error-log.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-error-log.js',
),
'javelin-behavior-fancy-datepicker' =>
array(
'uri' => '/res/0a1bc610/rsrc/js/application/core/behavior-fancy-datepicker.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-stratcom',
4 => 'javelin-vector',
),
'disk' => '/rsrc/js/application/core/behavior-fancy-datepicker.js',
),
'javelin-behavior-global-drag-and-drop' =>
array(
'uri' => '/res/73ae3fd1/rsrc/js/application/core/behavior-global-drag-and-drop.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-uri',
3 => 'javelin-mask',
4 => 'phabricator-drag-and-drop-file-upload',
),
'disk' => '/rsrc/js/application/core/behavior-global-drag-and-drop.js',
),
'javelin-behavior-herald-rule-editor' =>
array(
'uri' => '/res/77a0c945/rsrc/js/application/herald/herald-rule-editor.js',
'type' => 'js',
'requires' =>
array(
0 => 'herald-rule-editor',
1 => 'javelin-behavior',
),
'disk' => '/rsrc/js/application/herald/herald-rule-editor.js',
),
'javelin-behavior-konami' =>
array(
'uri' => '/res/2199602f/rsrc/js/application/core/behavior-konami.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/core/behavior-konami.js',
),
'javelin-behavior-lightbox-attachments' =>
array(
'uri' => '/res/08f5e202/rsrc/js/application/core/behavior-lightbox-attachments.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-mask',
4 => 'javelin-util',
5 => 'phabricator-busy',
),
'disk' => '/rsrc/js/application/core/behavior-lightbox-attachments.js',
),
'javelin-behavior-line-chart' =>
array(
'uri' => '/res/1aa5ac88/rsrc/js/application/maniphest/behavior-line-chart.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-vector',
),
'disk' => '/rsrc/js/application/maniphest/behavior-line-chart.js',
),
'javelin-behavior-maniphest-batch-editor' =>
array(
'uri' => '/res/d22661be/rsrc/js/application/maniphest/behavior-batch-editor.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-prefab',
4 => 'multirow-row-manager',
5 => 'javelin-json',
),
'disk' => '/rsrc/js/application/maniphest/behavior-batch-editor.js',
),
'javelin-behavior-maniphest-batch-selector' =>
array(
'uri' => '/res/398cf8d7/rsrc/js/application/maniphest/behavior-batch-selector.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/maniphest/behavior-batch-selector.js',
),
'javelin-behavior-maniphest-description-preview' =>
array(
'uri' => '/res/8acd6f07/rsrc/js/application/maniphest/behavior-task-preview.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-shaped-request',
),
'disk' => '/rsrc/js/application/maniphest/behavior-task-preview.js',
),
'javelin-behavior-maniphest-subpriority-editor' =>
array(
'uri' => '/res/5e02f19a/rsrc/js/application/maniphest/behavior-subpriorityeditor.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-magical-init',
2 => 'javelin-dom',
3 => 'javelin-vector',
4 => 'javelin-stratcom',
5 => 'javelin-workflow',
),
'disk' => '/rsrc/js/application/maniphest/behavior-subpriorityeditor.js',
),
'javelin-behavior-maniphest-transaction-controls' =>
array(
'uri' => '/res/62465554/rsrc/js/application/maniphest/behavior-transaction-controls.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'phabricator-prefab',
),
'disk' => '/rsrc/js/application/maniphest/behavior-transaction-controls.js',
),
'javelin-behavior-maniphest-transaction-expand' =>
array(
'uri' => '/res/966410de/rsrc/js/application/maniphest/behavior-transaction-expand.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-workflow',
3 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/maniphest/behavior-transaction-expand.js',
),
'javelin-behavior-maniphest-transaction-preview' =>
array(
'uri' => '/res/855c9f0c/rsrc/js/application/maniphest/behavior-transaction-preview.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-json',
4 => 'javelin-stratcom',
5 => 'phabricator-shaped-request',
),
'disk' => '/rsrc/js/application/maniphest/behavior-transaction-preview.js',
),
'javelin-behavior-owners-path-editor' =>
array(
'uri' => '/res/9cf78ffc/rsrc/js/application/owners/owners-path-editor.js',
'type' => 'js',
'requires' =>
array(
0 => 'owners-path-editor',
1 => 'javelin-behavior',
),
'disk' => '/rsrc/js/application/owners/owners-path-editor.js',
),
'javelin-behavior-phabricator-active-nav' =>
array(
'uri' => '/res/f879d4dd/rsrc/js/application/core/behavior-active-nav.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-vector',
3 => 'javelin-dom',
4 => 'javelin-uri',
),
'disk' => '/rsrc/js/application/core/behavior-active-nav.js',
),
'javelin-behavior-phabricator-autofocus' =>
array(
'uri' => '/res/2946bb89/rsrc/js/application/core/behavior-autofocus.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-autofocus.js',
),
+ 'javelin-behavior-phabricator-file-tree' =>
+ array(
+ 'uri' => '/res/e9c96597/rsrc/js/application/core/behavior-file-tree.js',
+ 'type' => 'js',
+ 'requires' =>
+ array(
+ 0 => 'javelin-behavior',
+ 1 => 'phabricator-keyboard-shortcut',
+ 2 => 'javelin-stratcom',
+ ),
+ 'disk' => '/rsrc/js/application/core/behavior-file-tree.js',
+ ),
'javelin-behavior-phabricator-home-reveal-tiles' =>
array(
- 'uri' => '/res/7230ca0c/rsrc/js/application/core/behavior-home-reveal-tiles.js',
+ 'uri' => '/res/b3c5cea9/rsrc/js/application/core/behavior-home-reveal-tiles.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-home-reveal-tiles.js',
),
'javelin-behavior-phabricator-keyboard-pager' =>
array(
'uri' => '/res/56d64eff/rsrc/js/application/core/behavior-keyboard-pager.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-uri',
2 => 'phabricator-keyboard-shortcut',
),
'disk' => '/rsrc/js/application/core/behavior-keyboard-pager.js',
),
'javelin-behavior-phabricator-keyboard-shortcuts' =>
array(
'uri' => '/res/c5eb65cd/rsrc/js/application/core/behavior-keyboard-shortcuts.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-workflow',
2 => 'javelin-json',
3 => 'javelin-dom',
4 => 'phabricator-keyboard-shortcut',
),
'disk' => '/rsrc/js/application/core/behavior-keyboard-shortcuts.js',
),
'javelin-behavior-phabricator-nav' =>
array(
- 'uri' => '/res/cec31f3f/rsrc/js/application/core/behavior-phabricator-nav.js',
+ 'uri' => '/res/222b9329/rsrc/js/application/core/behavior-phabricator-nav.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-behavior-device',
2 => 'javelin-stratcom',
3 => 'javelin-dom',
4 => 'javelin-magical-init',
5 => 'javelin-vector',
),
'disk' => '/rsrc/js/application/core/behavior-phabricator-nav.js',
),
'javelin-behavior-phabricator-notification-example' =>
array(
'uri' => '/res/a6d51998/rsrc/js/application/uiexample/notification-example.js',
'type' => 'js',
'requires' =>
array(
0 => 'phabricator-notification',
1 => 'javelin-stratcom',
2 => 'javelin-behavior',
3 => 'javelin-uri',
),
'disk' => '/rsrc/js/application/uiexample/notification-example.js',
),
'javelin-behavior-phabricator-object-selector' =>
array(
'uri' => '/res/0c4b0d82/rsrc/js/application/core/behavior-object-selector.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-request',
3 => 'javelin-util',
),
'disk' => '/rsrc/js/application/core/behavior-object-selector.js',
),
'javelin-behavior-phabricator-oncopy' =>
array(
'uri' => '/res/f490b8d1/rsrc/js/application/core/behavior-oncopy.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-oncopy.js',
),
'javelin-behavior-phabricator-remarkup-assist' =>
array(
'uri' => '/res/07406487/rsrc/js/application/core/behavior-phabricator-remarkup-assist.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'phabricator-textareautils',
),
'disk' => '/rsrc/js/application/core/behavior-phabricator-remarkup-assist.js',
),
'javelin-behavior-phabricator-search-typeahead' =>
array(
'uri' => '/res/046ab274/rsrc/js/application/core/behavior-search-typeahead.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-typeahead-ondemand-source',
2 => 'javelin-typeahead',
3 => 'javelin-dom',
4 => 'javelin-uri',
5 => 'javelin-util',
6 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/core/behavior-search-typeahead.js',
),
'javelin-behavior-phabricator-tooltips' =>
array(
'uri' => '/res/e0b344c6/rsrc/js/application/core/behavior-tooltip.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-behavior-device',
2 => 'javelin-stratcom',
3 => 'phabricator-tooltip',
),
'disk' => '/rsrc/js/application/core/behavior-tooltip.js',
),
'javelin-behavior-phabricator-transaction-comment-form' =>
array(
'uri' => '/res/acc3ada1/rsrc/js/application/transactions/behavior-transaction-comment-form.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-shaped-request',
),
'disk' => '/rsrc/js/application/transactions/behavior-transaction-comment-form.js',
),
'javelin-behavior-phabricator-transaction-list' =>
array(
'uri' => '/res/f1fbb474/rsrc/js/application/transactions/behavior-transaction-list.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-workflow',
3 => 'javelin-dom',
4 => 'javelin-fx',
),
'disk' => '/rsrc/js/application/transactions/behavior-transaction-list.js',
),
'javelin-behavior-phabricator-watch-anchor' =>
array(
'uri' => '/res/b20b1cc2/rsrc/js/application/core/behavior-watch-anchor.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-vector',
),
'disk' => '/rsrc/js/application/core/behavior-watch-anchor.js',
),
'javelin-behavior-phame-post-preview' =>
array(
'uri' => '/res/ac4c503a/rsrc/js/application/phame/phame-post-preview.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-shaped-request',
),
'disk' => '/rsrc/js/application/phame/phame-post-preview.js',
),
'javelin-behavior-pholio-mock-view' =>
array(
- 'uri' => '/res/10fbdca1/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
+ 'uri' => '/res/518a169e/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
+ 2 => 'javelin-dom',
+ 3 => 'javelin-vector',
+ 4 => 'javelin-magical-init',
+ 5 => 'javelin-request',
),
'disk' => '/rsrc/js/application/pholio/behavior-pholio-mock-view.js',
),
'javelin-behavior-phriction-document-preview' =>
array(
'uri' => '/res/f1665ecd/rsrc/js/application/phriction/phriction-document-preview.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-shaped-request',
),
'disk' => '/rsrc/js/application/phriction/phriction-document-preview.js',
),
'javelin-behavior-ponder-feedback-preview' =>
array(
'uri' => '/res/2e802dd9/rsrc/js/application/ponder/behavior-comment-preview.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'phabricator-shaped-request',
),
'disk' => '/rsrc/js/application/ponder/behavior-comment-preview.js',
),
'javelin-behavior-ponder-votebox' =>
array(
'uri' => '/res/9d091af3/rsrc/js/application/ponder/behavior-votebox.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-stratcom',
4 => 'javelin-request',
),
'disk' => '/rsrc/js/application/ponder/behavior-votebox.js',
),
'javelin-behavior-project-create' =>
array(
'uri' => '/res/e91f3f8f/rsrc/js/application/projects/behavior-project-create.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-workflow',
),
'disk' => '/rsrc/js/application/projects/behavior-project-create.js',
),
'javelin-behavior-refresh-csrf' =>
array(
'uri' => '/res/6fd76d0f/rsrc/js/application/core/behavior-refresh-csrf.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-request',
1 => 'javelin-behavior',
2 => 'javelin-dom',
3 => 'phabricator-busy',
),
'disk' => '/rsrc/js/application/core/behavior-refresh-csrf.js',
),
'javelin-behavior-repository-crossreference' =>
array(
'uri' => '/res/244c5251/rsrc/js/application/repository/repository-crossreference.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-uri',
),
'disk' => '/rsrc/js/application/repository/repository-crossreference.js',
),
'javelin-behavior-stripe-payment-form' =>
array(
'uri' => '/res/87c7b043/rsrc/js/application/phortune/behavior-stripe-payment-form.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-json',
3 => 'stripe-core',
),
'disk' => '/rsrc/js/application/phortune/behavior-stripe-payment-form.js',
),
'javelin-behavior-toggle-class' =>
array(
'uri' => '/res/fa818e0f/rsrc/js/application/core/behavior-toggle-class.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-toggle-class.js',
),
'javelin-behavior-view-placeholder' =>
array(
'uri' => '/res/5b89bdf5/rsrc/js/javelin/ext/view/ViewPlaceholder.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-view-renderer',
),
'disk' => '/rsrc/js/javelin/ext/view/ViewPlaceholder.js',
),
'javelin-behavior-workflow' =>
array(
'uri' => '/res/2c99beaf/rsrc/js/application/core/behavior-workflow.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-workflow',
3 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-workflow.js',
),
'javelin-color' =>
array(
'uri' => '/res/b0439fc9/rsrc/js/javelin/ext/fx/Color.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/ext/fx/Color.js',
),
'javelin-cookie' =>
array(
'uri' => '/res/a9cddab0/rsrc/js/javelin/lib/Cookie.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/lib/Cookie.js',
),
'javelin-dom' =>
array(
'uri' => '/res/459f3c08/rsrc/js/javelin/lib/DOM.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-magical-init',
1 => 'javelin-install',
2 => 'javelin-util',
3 => 'javelin-vector',
4 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/javelin/lib/DOM.js',
),
'javelin-dynval' =>
array(
'uri' => '/res/d89c6f88/rsrc/js/javelin/ext/reactor/core/DynVal.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-reactornode',
2 => 'javelin-util',
3 => 'javelin-reactor',
),
'disk' => '/rsrc/js/javelin/ext/reactor/core/DynVal.js',
),
'javelin-event' =>
array(
- 'uri' => '/res/3815b473/rsrc/js/javelin/core/Event.js',
+ 'uri' => '/res/e6582051/rsrc/js/javelin/core/Event.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/core/Event.js',
),
'javelin-fx' =>
array(
'uri' => '/res/30ef0914/rsrc/js/javelin/ext/fx/FX.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-color',
1 => 'javelin-install',
2 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/ext/fx/FX.js',
),
'javelin-history' =>
array(
'uri' => '/res/9bb36651/rsrc/js/javelin/lib/History.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-stratcom',
1 => 'javelin-install',
2 => 'javelin-uri',
3 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/lib/History.js',
),
'javelin-install' =>
array(
'uri' => '/res/cab679ff/rsrc/js/javelin/core/install.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-util',
1 => 'javelin-magical-init',
),
'disk' => '/rsrc/js/javelin/core/install.js',
),
'javelin-json' =>
array(
'uri' => '/res/561b8056/rsrc/js/javelin/lib/JSON.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/lib/JSON.js',
),
'javelin-magical-init' =>
array(
'uri' => '/res/4f3c705c/rsrc/js/javelin/core/init.js',
'type' => 'js',
'requires' =>
array(
),
'disk' => '/rsrc/js/javelin/core/init.js',
),
'javelin-mask' =>
array(
'uri' => '/res/d2a35fff/rsrc/js/javelin/lib/Mask.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
),
'disk' => '/rsrc/js/javelin/lib/Mask.js',
),
'javelin-reactor' =>
array(
'uri' => '/res/dfd87f3c/rsrc/js/javelin/ext/reactor/core/Reactor.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/ext/reactor/core/Reactor.js',
),
'javelin-reactor-dom' =>
array(
'uri' => '/res/701b6f39/rsrc/js/javelin/ext/reactor/dom/RDOM.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-dom',
1 => 'javelin-dynval',
2 => 'javelin-reactornode',
3 => 'javelin-install',
4 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/ext/reactor/dom/RDOM.js',
),
'javelin-reactor-node-calmer' =>
array(
'uri' => '/res/5a35920a/rsrc/js/javelin/ext/reactor/core/ReactorNodeCalmer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-reactor',
2 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/ext/reactor/core/ReactorNodeCalmer.js',
),
'javelin-reactornode' =>
array(
'uri' => '/res/f278cc27/rsrc/js/javelin/ext/reactor/core/ReactorNode.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-reactor',
2 => 'javelin-util',
3 => 'javelin-reactor-node-calmer',
),
'disk' => '/rsrc/js/javelin/ext/reactor/core/ReactorNode.js',
),
'javelin-request' =>
array(
'uri' => '/res/e25d75b3/rsrc/js/javelin/lib/Request.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-stratcom',
2 => 'javelin-util',
3 => 'javelin-behavior',
4 => 'javelin-json',
5 => 'javelin-dom',
6 => 'javelin-resource',
),
'disk' => '/rsrc/js/javelin/lib/Request.js',
),
'javelin-resource' =>
array(
'uri' => '/res/d5a3f835/rsrc/js/javelin/lib/Resource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-magical-init',
1 => 'javelin-stratcom',
2 => 'javelin-util',
3 => 'javelin-uri',
),
'disk' => '/rsrc/js/javelin/lib/Resource.js',
),
'javelin-stratcom' =>
array(
'uri' => '/res/c81f64eb/rsrc/js/javelin/core/Stratcom.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-event',
2 => 'javelin-util',
3 => 'javelin-magical-init',
),
'disk' => '/rsrc/js/javelin/core/Stratcom.js',
),
'javelin-tokenizer' =>
array(
'uri' => '/res/c75c9e12/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-dom',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
),
'javelin-typeahead' =>
array(
'uri' => '/res/dccb789e/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-vector',
3 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
),
'javelin-typeahead-composite-source' =>
array(
'uri' => '/res/99705f64/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-typeahead-source',
2 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadCompositeSource.js',
),
'javelin-typeahead-normalizer' =>
array(
'uri' => '/res/a9e97c0d/rsrc/js/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js',
),
'javelin-typeahead-ondemand-source' =>
array(
'uri' => '/res/81e531aa/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-request',
4 => 'javelin-typeahead-source',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js',
),
'javelin-typeahead-preloaded-source' =>
array(
'uri' => '/res/d464efd2/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-request',
4 => 'javelin-typeahead-source',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js',
),
'javelin-typeahead-source' =>
array(
'uri' => '/res/74b1f091/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-typeahead-normalizer',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadSource.js',
),
'javelin-typeahead-static-source' =>
array(
'uri' => '/res/c8e247fc/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-typeahead-source',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js',
),
'javelin-uri' =>
array(
'uri' => '/res/c107d858/rsrc/js/javelin/lib/URI.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/javelin/lib/URI.js',
),
'javelin-util' =>
array(
'uri' => '/res/25786b6c/rsrc/js/javelin/core/util.js',
'type' => 'js',
'requires' =>
array(
),
'disk' => '/rsrc/js/javelin/core/util.js',
),
'javelin-vector' =>
array(
'uri' => '/res/f240bdb3/rsrc/js/javelin/lib/Vector.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-event',
),
'disk' => '/rsrc/js/javelin/lib/Vector.js',
),
'javelin-view' =>
array(
'uri' => '/res/b98657a7/rsrc/js/javelin/ext/view/View.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/ext/view/View.js',
),
'javelin-view-html' =>
array(
'uri' => '/res/7e5a2122/rsrc/js/javelin/ext/view/HTMLView.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
),
'disk' => '/rsrc/js/javelin/ext/view/HTMLView.js',
),
'javelin-view-interpreter' =>
array(
'uri' => '/res/17e911ca/rsrc/js/javelin/ext/view/ViewInterpreter.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-view',
1 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/ext/view/ViewInterpreter.js',
),
'javelin-view-renderer' =>
array(
'uri' => '/res/db4ed5a2/rsrc/js/javelin/ext/view/ViewRenderer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/ext/view/ViewRenderer.js',
),
'javelin-view-visitor' =>
array(
'uri' => '/res/0ef9dc43/rsrc/js/javelin/ext/view/ViewVisitor.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/ext/view/ViewVisitor.js',
),
'javelin-workflow' =>
array(
'uri' => '/res/519c4e1a/rsrc/js/javelin/lib/Workflow.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-stratcom',
1 => 'javelin-request',
2 => 'javelin-dom',
3 => 'javelin-vector',
4 => 'javelin-install',
5 => 'javelin-util',
6 => 'javelin-mask',
7 => 'javelin-uri',
),
'disk' => '/rsrc/js/javelin/lib/Workflow.js',
),
'lightbox-attachment-css' =>
array(
'uri' => '/res/4657e15d/rsrc/css/aphront/lightbox-attachment.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/lightbox-attachment.css',
),
'maniphest-batch-editor' =>
array(
'uri' => '/res/fb15d744/rsrc/css/application/maniphest/batch-editor.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/maniphest/batch-editor.css',
),
'maniphest-report-css' =>
array(
'uri' => '/res/2e633fcf/rsrc/css/application/maniphest/report.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/maniphest/report.css',
),
'maniphest-task-edit-css' =>
array(
'uri' => '/res/68c7863e/rsrc/css/application/maniphest/task-edit.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/maniphest/task-edit.css',
),
'maniphest-task-summary-css' =>
array(
'uri' => '/res/14e825ce/rsrc/css/application/maniphest/task-summary.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/maniphest/task-summary.css',
),
'maniphest-transaction-detail-css' =>
array(
'uri' => '/res/fb430d3e/rsrc/css/application/maniphest/transaction-detail.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/maniphest/transaction-detail.css',
),
'multirow-row-manager' =>
array(
'uri' => '/res/0a9b3dee/rsrc/js/application/core/MultirowRowManager.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-util',
),
'disk' => '/rsrc/js/application/core/MultirowRowManager.js',
),
'owners-path-editor' =>
array(
'uri' => '/res/29b68354/rsrc/js/application/owners/OwnersPathEditor.js',
'type' => 'js',
'requires' =>
array(
0 => 'multirow-row-manager',
1 => 'javelin-install',
2 => 'path-typeahead',
3 => 'javelin-dom',
4 => 'javelin-util',
5 => 'phabricator-prefab',
),
'disk' => '/rsrc/js/application/owners/OwnersPathEditor.js',
),
'owners-path-editor-css' =>
array(
'uri' => '/res/4fcaabf6/rsrc/css/application/owners/owners-path-editor.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/owners/owners-path-editor.css',
),
'path-typeahead' =>
array(
'uri' => '/res/50246fb6/rsrc/js/application/herald/PathTypeahead.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-typeahead',
2 => 'javelin-dom',
3 => 'javelin-request',
4 => 'javelin-typeahead-ondemand-source',
5 => 'javelin-util',
),
'disk' => '/rsrc/js/application/herald/PathTypeahead.js',
),
'phabricator-action-list-view-css' =>
array(
'uri' => '/res/7a67c3b9/rsrc/css/layout/phabricator-action-list-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-action-list-view.css',
),
'phabricator-application-launch-view-css' =>
array(
'uri' => '/res/8aee0702/rsrc/css/application/base/phabricator-application-launch-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/base/phabricator-application-launch-view.css',
),
'phabricator-busy' =>
array(
'uri' => '/res/6ec372e1/rsrc/js/application/core/Busy.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/Busy.js',
),
'phabricator-chatlog-css' =>
array(
'uri' => '/res/f6631adc/rsrc/css/application/chatlog/chatlog.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/chatlog/chatlog.css',
),
'phabricator-content-source-view-css' =>
array(
'uri' => '/res/8c738a93/rsrc/css/application/contentsource/content-source-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/contentsource/content-source-view.css',
),
'phabricator-core-buttons-css' =>
array(
'uri' => '/res/7320ca6d/rsrc/css/core/buttons.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/core/buttons.css',
),
'phabricator-core-css' =>
array(
'uri' => '/res/03c97d00/rsrc/css/core/core.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/core/core.css',
),
'phabricator-countdown-css' =>
array(
'uri' => '/res/0f646281/rsrc/css/application/countdown/timer.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/countdown/timer.css',
),
'phabricator-crumbs-view-css' =>
array(
'uri' => '/res/69fdba64/rsrc/css/layout/phabricator-crumbs-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-crumbs-view.css',
),
'phabricator-directory-css' =>
array(
'uri' => '/res/61afca2b/rsrc/css/application/directory/phabricator-directory.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/directory/phabricator-directory.css',
),
'phabricator-drag-and-drop-file-upload' =>
array(
'uri' => '/res/ce71f19a/rsrc/js/application/core/DragAndDropFileUpload.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-request',
3 => 'javelin-dom',
4 => 'javelin-uri',
5 => 'phabricator-file-upload',
),
'disk' => '/rsrc/js/application/core/DragAndDropFileUpload.js',
),
'phabricator-dropdown-menu' =>
array(
'uri' => '/res/2b4aa4d8/rsrc/js/application/core/DropdownMenu.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-vector',
4 => 'javelin-stratcom',
5 => 'phabricator-menu-item',
),
'disk' => '/rsrc/js/application/core/DropdownMenu.js',
),
'phabricator-fatal-config-template-css' =>
array(
'uri' => '/res/6e1a8d22/rsrc/css/application/config/config-template.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/config/config-template.css',
),
'phabricator-feed-css' =>
array(
'uri' => '/res/94a04b24/rsrc/css/application/feed/feed.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/feed/feed.css',
),
'phabricator-file-upload' =>
array(
'uri' => '/res/2de10295/rsrc/js/application/core/FileUpload.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'phabricator-notification',
),
'disk' => '/rsrc/js/application/core/FileUpload.js',
),
'phabricator-filetree-view-css' =>
array(
'uri' => '/res/c912ed91/rsrc/css/layout/phabricator-filetree-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-filetree-view.css',
),
'phabricator-flag-css' =>
array(
'uri' => '/res/2eee890a/rsrc/css/application/flag/flag.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/flag/flag.css',
),
'phabricator-form-view-css' =>
array(
'uri' => '/res/bdec7be5/rsrc/css/layout/phabricator-form-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-form-view.css',
),
'phabricator-header-view-css' =>
array(
- 'uri' => '/res/88ef478c/rsrc/css/layout/phabricator-header-view.css',
+ 'uri' => '/res/585b771c/rsrc/css/layout/phabricator-header-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-header-view.css',
),
'phabricator-jump-nav' =>
array(
'uri' => '/res/2e0e2211/rsrc/css/application/directory/phabricator-jump-nav.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/directory/phabricator-jump-nav.css',
),
'phabricator-keyboard-shortcut' =>
array(
'uri' => '/res/beed38cd/rsrc/js/application/core/KeyboardShortcut.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'phabricator-keyboard-shortcut-manager',
),
'disk' => '/rsrc/js/application/core/KeyboardShortcut.js',
),
'phabricator-keyboard-shortcut-manager' =>
array(
'uri' => '/res/0be80136/rsrc/js/application/core/KeyboardShortcutManager.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-dom',
4 => 'javelin-vector',
),
'disk' => '/rsrc/js/application/core/KeyboardShortcutManager.js',
),
'phabricator-main-menu-view' =>
array(
'uri' => '/res/597e394b/rsrc/css/application/base/main-menu-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/base/main-menu-view.css',
),
'phabricator-menu-item' =>
array(
'uri' => '/res/32fc2325/rsrc/js/application/core/DropdownMenuItem.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/DropdownMenuItem.js',
),
'phabricator-nav-view-css' =>
array(
'uri' => '/res/f3c78a53/rsrc/css/aphront/phabricator-nav-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/phabricator-nav-view.css',
),
'phabricator-notification' =>
array(
'uri' => '/res/ad727561/rsrc/js/application/core/Notification.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-stratcom',
3 => 'javelin-util',
4 => 'phabricator-notification-css',
),
'disk' => '/rsrc/js/application/core/Notification.js',
),
'phabricator-notification-css' =>
array(
'uri' => '/res/664b9bec/rsrc/css/aphront/notification.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/notification.css',
),
'phabricator-notification-menu-css' =>
array(
'uri' => '/res/b7cc25af/rsrc/css/application/base/notification-menu.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/base/notification-menu.css',
),
'phabricator-object-item-list-view-css' =>
array(
'uri' => '/res/2fb97c5c/rsrc/css/layout/phabricator-object-item-list-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-object-item-list-view.css',
),
'phabricator-object-list-view-css' =>
array(
'uri' => '/res/4f183668/rsrc/css/application/projects/phabricator-object-list-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/projects/phabricator-object-list-view.css',
),
'phabricator-object-selector-css' =>
array(
'uri' => '/res/7eb4c705/rsrc/css/application/objectselector/object-selector.css',
'type' => 'css',
'requires' =>
array(
0 => 'aphront-dialog-view-css',
),
'disk' => '/rsrc/css/application/objectselector/object-selector.css',
),
'phabricator-paste-file-upload' =>
array(
'uri' => '/res/b0b8afd8/rsrc/js/application/core/PasteFileUpload.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-request',
3 => 'javelin-dom',
4 => 'javelin-uri',
),
'disk' => '/rsrc/js/application/core/PasteFileUpload.js',
),
'phabricator-pinboard-view-css' =>
array(
'uri' => '/res/3a24d210/rsrc/css/layout/phabricator-pinboard-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-pinboard-view.css',
),
'phabricator-prefab' =>
array(
'uri' => '/res/2734e45f/rsrc/js/application/core/Prefab.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-typeahead',
4 => 'javelin-tokenizer',
5 => 'javelin-typeahead-preloaded-source',
6 => 'javelin-typeahead-ondemand-source',
7 => 'javelin-dom',
8 => 'javelin-stratcom',
9 => 'javelin-util',
),
'disk' => '/rsrc/js/application/core/Prefab.js',
),
'phabricator-profile-css' =>
array(
'uri' => '/res/9869d10b/rsrc/css/application/profile/profile-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/profile/profile-view.css',
),
'phabricator-profile-header-css' =>
array(
'uri' => '/res/4b1cb23b/rsrc/css/application/profile/profile-header-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/profile/profile-header-view.css',
),
'phabricator-project-tag-css' =>
array(
'uri' => '/res/6b0a5223/rsrc/css/application/projects/project-tag.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/projects/project-tag.css',
),
'phabricator-property-list-view-css' =>
array(
'uri' => '/res/cd84ee5a/rsrc/css/layout/phabricator-property-list-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-property-list-view.css',
),
'phabricator-remarkup-css' =>
array(
'uri' => '/res/f444d7c9/rsrc/css/core/remarkup.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/core/remarkup.css',
),
'phabricator-search-results-css' =>
array(
'uri' => '/res/f8a86e27/rsrc/css/application/search/search-results.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/search/search-results.css',
),
'phabricator-shaped-request' =>
array(
'uri' => '/res/fbdb92db/rsrc/js/application/core/ShapedRequest.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-request',
),
'disk' => '/rsrc/js/application/core/ShapedRequest.js',
),
'phabricator-side-menu-view-css' =>
array(
'uri' => '/res/28a1e092/rsrc/css/layout/phabricator-side-menu-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-side-menu-view.css',
),
'phabricator-slowvote-css' =>
array(
'uri' => '/res/94d20443/rsrc/css/application/slowvote/slowvote.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/slowvote/slowvote.css',
),
'phabricator-source-code-view-css' =>
array(
'uri' => '/res/9373e769/rsrc/css/layout/phabricator-source-code-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-source-code-view.css',
),
'phabricator-standard-page-view' =>
array(
'uri' => '/res/5f013c46/rsrc/css/application/base/standard-page-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/base/standard-page-view.css',
),
'phabricator-tag-view-css' =>
array(
'uri' => '/res/e10bf844/rsrc/css/layout/phabricator-tag-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-tag-view.css',
),
'phabricator-textareautils' =>
array(
'uri' => '/res/703614ea/rsrc/js/application/core/TextAreaUtils.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/application/core/TextAreaUtils.js',
),
'phabricator-timeline-view-css' =>
array(
'uri' => '/res/d87e1d60/rsrc/css/layout/phabricator-timeline-view.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/layout/phabricator-timeline-view.css',
),
'phabricator-tooltip' =>
array(
'uri' => '/res/55d76b9b/rsrc/js/application/core/ToolTip.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-vector',
),
'disk' => '/rsrc/js/application/core/ToolTip.js',
),
'phabricator-transaction-view-css' =>
array(
'uri' => '/res/4c5c16dc/rsrc/css/aphront/transaction.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/aphront/transaction.css',
),
'phabricator-ui-example-css' =>
array(
'uri' => '/res/376ab671/rsrc/css/application/uiexample/example.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/uiexample/example.css',
),
'phabricator-uiexample-javelin-view' =>
array(
'uri' => '/res/a2ce2cfc/rsrc/js/application/uiexample/JavelinViewExample.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
2 => 'javelin-util',
3 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/uiexample/JavelinViewExample.js',
),
'phabricator-uiexample-reactor-button' =>
array(
'uri' => '/res/142127f6/rsrc/js/application/uiexample/ReactorButtonExample.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-reactor-dom',
),
'disk' => '/rsrc/js/application/uiexample/ReactorButtonExample.js',
),
'phabricator-uiexample-reactor-checkbox' =>
array(
'uri' => '/res/c75cb9e9/rsrc/js/application/uiexample/ReactorCheckboxExample.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-reactor-dom',
),
'disk' => '/rsrc/js/application/uiexample/ReactorCheckboxExample.js',
),
'phabricator-uiexample-reactor-focus' =>
array(
'uri' => '/res/3cc992eb/rsrc/js/application/uiexample/ReactorFocusExample.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-reactor-dom',
),
'disk' => '/rsrc/js/application/uiexample/ReactorFocusExample.js',
),
'phabricator-uiexample-reactor-input' =>
array(
'uri' => '/res/4953da16/rsrc/js/application/uiexample/ReactorInputExample.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-reactor-dom',
5 => 'javelin-view-html',
6 => 'javelin-view-interpreter',
7 => 'javelin-view-renderer',
),
'disk' => '/rsrc/js/application/uiexample/ReactorInputExample.js',
),
'phabricator-uiexample-reactor-mouseover' =>
array(
'uri' => '/res/52a355b6/rsrc/js/application/uiexample/ReactorMouseoverExample.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-reactor-dom',
),
'disk' => '/rsrc/js/application/uiexample/ReactorMouseoverExample.js',
),
'phabricator-uiexample-reactor-radio' =>
array(
'uri' => '/res/ae87f3af/rsrc/js/application/uiexample/ReactorRadioExample.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-reactor-dom',
),
'disk' => '/rsrc/js/application/uiexample/ReactorRadioExample.js',
),
'phabricator-uiexample-reactor-select' =>
array(
'uri' => '/res/23cb448a/rsrc/js/application/uiexample/ReactorSelectExample.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-reactor-dom',
),
'disk' => '/rsrc/js/application/uiexample/ReactorSelectExample.js',
),
'phabricator-uiexample-reactor-sendclass' =>
array(
'uri' => '/res/8cd34264/rsrc/js/application/uiexample/ReactorSendClassExample.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-reactor-dom',
),
'disk' => '/rsrc/js/application/uiexample/ReactorSendClassExample.js',
),
'phabricator-uiexample-reactor-sendproperties' =>
array(
'uri' => '/res/18af54aa/rsrc/js/application/uiexample/ReactorSendPropertiesExample.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-view',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-reactor-dom',
),
'disk' => '/rsrc/js/application/uiexample/ReactorSendPropertiesExample.js',
),
'phabricator-zindex-css' =>
array(
'uri' => '/res/fcbf82ad/rsrc/css/core/z-index.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/core/z-index.css',
),
'phame-css' =>
array(
'uri' => '/res/8e3edb71/rsrc/css/application/phame/phame.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/phame/phame.css',
),
'pholio-css' =>
array(
- 'uri' => '/res/f101ad7c/rsrc/css/application/pholio/pholio.css',
+ 'uri' => '/res/9de6e0b2/rsrc/css/application/pholio/pholio.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/pholio/pholio.css',
),
'phriction-document-css' =>
array(
'uri' => '/res/8d09bd7f/rsrc/css/application/phriction/phriction-document-css.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/phriction/phriction-document-css.css',
),
'ponder-comment-table-css' =>
array(
'uri' => '/res/a1bb9056/rsrc/css/application/ponder/comments.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/ponder/comments.css',
),
'ponder-core-view-css' =>
array(
'uri' => '/res/3a2d5e18/rsrc/css/application/ponder/core.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/ponder/core.css',
),
'ponder-feed-view-css' =>
array(
'uri' => '/res/df22bd20/rsrc/css/application/ponder/feed.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/ponder/feed.css',
),
'ponder-post-css' =>
array(
'uri' => '/res/013b9e2c/rsrc/css/application/ponder/post.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/ponder/post.css',
),
'ponder-vote-css' =>
array(
'uri' => '/res/ea8316c2/rsrc/css/application/ponder/vote.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/ponder/vote.css',
),
'raphael-core' =>
array(
'uri' => '/res/3f48575a/rsrc/js/raphael/raphael.js',
'type' => 'js',
'requires' =>
array(
),
'disk' => '/rsrc/js/raphael/raphael.js',
),
'raphael-g' =>
array(
'uri' => '/res/b07e5245/rsrc/js/raphael/g.raphael.js',
'type' => 'js',
'requires' =>
array(
),
'disk' => '/rsrc/js/raphael/g.raphael.js',
),
'raphael-g-line' =>
array(
'uri' => '/res/a59c8556/rsrc/js/raphael/g.raphael.line.js',
'type' => 'js',
'requires' =>
array(
),
'disk' => '/rsrc/js/raphael/g.raphael.line.js',
),
'setup-issue-css' =>
array(
'uri' => '/res/efbb3673/rsrc/css/application/config/setup-issue.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/config/setup-issue.css',
),
'sprite-apps-css' =>
array(
'uri' => '/res/8de495b4/rsrc/css/sprite-apps.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/sprite-apps.css',
),
'sprite-apps-large-css' =>
array(
'uri' => '/res/174143b7/rsrc/css/sprite-apps-large.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/sprite-apps-large.css',
),
'sprite-apps-xlarge-css' =>
array(
'uri' => '/res/33a8e644/rsrc/css/sprite-apps-xlarge.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/sprite-apps-xlarge.css',
),
'sprite-conpher-css' =>
array(
- 'uri' => '/res/f640f0c5/rsrc/css/sprite-conph.css',
+ 'uri' => '/res/89821322/rsrc/css/sprite-conph.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/sprite-conph.css',
),
'sprite-gradient-css' =>
array(
'uri' => '/res/e62e7a0f/rsrc/css/sprite-gradient.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/sprite-gradient.css',
),
'sprite-icon-css' =>
array(
'uri' => '/res/e7d63fcf/rsrc/css/sprite-icon.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/sprite-icon.css',
),
'sprite-menu-css' =>
array(
'uri' => '/res/8e6624b0/rsrc/css/sprite-menu.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/sprite-menu.css',
),
'stripe-core' =>
array(
'uri' => '/res/3b0f0ad4/rsrc/js/stripe/stripe_core.js',
'type' => 'js',
'requires' =>
array(
),
'disk' => '/rsrc/js/stripe/stripe_core.js',
),
'stripe-payment-form-css' =>
array(
'uri' => '/res/634a6371/rsrc/css/application/phortune/stripe-payment-form.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/application/phortune/stripe-payment-form.css',
),
'syntax-highlighting-css' =>
array(
'uri' => '/res/cb3b9dc0/rsrc/css/core/syntax.css',
'type' => 'css',
'requires' =>
array(
),
'disk' => '/rsrc/css/core/syntax.css',
),
), array(
'packages' =>
array(
- '0e6165d0' =>
+ '4b569463' =>
array(
'name' => 'core.pkg.css',
'symbols' =>
array(
0 => 'phabricator-core-css',
1 => 'phabricator-zindex-css',
2 => 'phabricator-core-buttons-css',
3 => 'phabricator-standard-page-view',
4 => 'aphront-dialog-view-css',
5 => 'aphront-form-view-css',
6 => 'aphront-panel-view-css',
7 => 'aphront-table-view-css',
8 => 'aphront-crumbs-view-css',
9 => 'aphront-tokenizer-control-css',
10 => 'aphront-typeahead-control-css',
11 => 'aphront-list-filter-view-css',
12 => 'phabricator-directory-css',
13 => 'phabricator-jump-nav',
14 => 'phabricator-remarkup-css',
15 => 'syntax-highlighting-css',
16 => 'aphront-pager-view-css',
17 => 'phabricator-transaction-view-css',
18 => 'aphront-tooltip-css',
19 => 'phabricator-flag-css',
20 => 'aphront-error-view-css',
21 => 'sprite-icon-css',
22 => 'sprite-gradient-css',
23 => 'sprite-menu-css',
24 => 'sprite-apps-large-css',
25 => 'phabricator-main-menu-view',
26 => 'phabricator-notification-css',
27 => 'phabricator-notification-menu-css',
28 => 'lightbox-attachment-css',
29 => 'phabricator-header-view-css',
30 => 'phabricator-form-view-css',
31 => 'phabricator-filetree-view-css',
32 => 'phabricator-nav-view-css',
33 => 'phabricator-side-menu-view-css',
34 => 'phabricator-crumbs-view-css',
35 => 'phabricator-object-item-list-view-css',
36 => 'global-drag-and-drop-css',
),
- 'uri' => '/res/pkg/0e6165d0/core.pkg.css',
+ 'uri' => '/res/pkg/4b569463/core.pkg.css',
'type' => 'css',
),
- 'ff199687' =>
+ 'bc0774e5' =>
array(
'name' => 'core.pkg.js',
'symbols' =>
array(
0 => 'javelin-behavior-aphront-basic-tokenizer',
1 => 'javelin-behavior-workflow',
2 => 'javelin-behavior-aphront-form-disable-on-submit',
3 => 'phabricator-keyboard-shortcut-manager',
4 => 'phabricator-keyboard-shortcut',
5 => 'javelin-behavior-phabricator-keyboard-shortcuts',
6 => 'javelin-behavior-refresh-csrf',
7 => 'javelin-behavior-phabricator-watch-anchor',
8 => 'javelin-behavior-phabricator-autofocus',
9 => 'phabricator-paste-file-upload',
10 => 'phabricator-menu-item',
11 => 'phabricator-dropdown-menu',
12 => 'javelin-behavior-phabricator-oncopy',
13 => 'phabricator-tooltip',
14 => 'javelin-behavior-phabricator-tooltips',
15 => 'phabricator-prefab',
16 => 'javelin-behavior-device',
17 => 'javelin-behavior-toggle-class',
18 => 'javelin-behavior-lightbox-attachments',
19 => 'phabricator-busy',
20 => 'javelin-aphlict',
21 => 'phabricator-notification',
22 => 'javelin-behavior-aphlict-listen',
23 => 'javelin-behavior-phabricator-search-typeahead',
24 => 'javelin-behavior-konami',
25 => 'javelin-behavior-aphlict-dropdown',
26 => 'javelin-behavior-phabricator-active-nav',
27 => 'javelin-behavior-phabricator-nav',
28 => 'javelin-behavior-phabricator-remarkup-assist',
29 => 'phabricator-textareautils',
30 => 'phabricator-file-upload',
31 => 'javelin-behavior-global-drag-and-drop',
32 => 'javelin-behavior-phabricator-home-reveal-tiles',
),
- 'uri' => '/res/pkg/ff199687/core.pkg.js',
+ 'uri' => '/res/pkg/bc0774e5/core.pkg.js',
'type' => 'js',
),
- '74593df4' =>
+ '3e0098ea' =>
array(
'name' => 'darkconsole.pkg.js',
'symbols' =>
array(
0 => 'javelin-behavior-dark-console',
1 => 'javelin-behavior-error-log',
),
- 'uri' => '/res/pkg/74593df4/darkconsole.pkg.js',
+ 'uri' => '/res/pkg/3e0098ea/darkconsole.pkg.js',
'type' => 'js',
),
'8aaacd1b' =>
array(
'name' => 'differential.pkg.css',
'symbols' =>
array(
0 => 'differential-core-view-css',
1 => 'differential-changeset-view-css',
2 => 'differential-results-table-css',
3 => 'differential-revision-history-css',
4 => 'differential-revision-list-css',
5 => 'differential-table-of-contents-css',
6 => 'differential-revision-comment-css',
7 => 'differential-revision-add-comment-css',
8 => 'differential-revision-comment-list-css',
9 => 'phabricator-object-selector-css',
10 => 'phabricator-content-source-view-css',
11 => 'differential-local-commits-view-css',
12 => 'inline-comment-summary-css',
),
'uri' => '/res/pkg/8aaacd1b/differential.pkg.css',
'type' => 'css',
),
- '9dae5f20' =>
+ '95d0d865' =>
array(
'name' => 'differential.pkg.js',
'symbols' =>
array(
0 => 'phabricator-drag-and-drop-file-upload',
1 => 'phabricator-shaped-request',
2 => 'javelin-behavior-differential-feedback-preview',
3 => 'javelin-behavior-differential-edit-inline-comments',
4 => 'javelin-behavior-differential-populate',
5 => 'javelin-behavior-differential-show-more',
6 => 'javelin-behavior-differential-diff-radios',
7 => 'javelin-behavior-differential-accept-with-errors',
8 => 'javelin-behavior-differential-comment-jump',
9 => 'javelin-behavior-differential-add-reviewers-and-ccs',
10 => 'javelin-behavior-differential-keyboard-navigation',
11 => 'javelin-behavior-aphront-drag-and-drop',
12 => 'javelin-behavior-aphront-drag-and-drop-textarea',
13 => 'javelin-behavior-phabricator-object-selector',
14 => 'javelin-behavior-repository-crossreference',
15 => 'differential-inline-comment-editor',
16 => 'javelin-behavior-differential-dropdown-menus',
17 => 'javelin-behavior-differential-toggle-files',
18 => 'javelin-behavior-differential-user-select',
),
- 'uri' => '/res/pkg/9dae5f20/differential.pkg.js',
+ 'uri' => '/res/pkg/95d0d865/differential.pkg.js',
'type' => 'js',
),
'c8ce2d88' =>
array(
'name' => 'diffusion.pkg.css',
'symbols' =>
array(
0 => 'diffusion-commit-view-css',
1 => 'diffusion-icons-css',
),
'uri' => '/res/pkg/c8ce2d88/diffusion.pkg.css',
'type' => 'css',
),
'f96657b8' =>
array(
'name' => 'diffusion.pkg.js',
'symbols' =>
array(
0 => 'javelin-behavior-diffusion-pull-lastmodified',
1 => 'javelin-behavior-diffusion-commit-graph',
2 => 'javelin-behavior-audit-preview',
),
'uri' => '/res/pkg/f96657b8/diffusion.pkg.js',
'type' => 'js',
),
- '1c6f020b' =>
+ 'd466c034' =>
array(
'name' => 'javelin.pkg.js',
'symbols' =>
array(
0 => 'javelin-util',
1 => 'javelin-install',
2 => 'javelin-event',
3 => 'javelin-stratcom',
4 => 'javelin-behavior',
5 => 'javelin-resource',
6 => 'javelin-request',
7 => 'javelin-vector',
8 => 'javelin-dom',
9 => 'javelin-json',
10 => 'javelin-uri',
11 => 'javelin-workflow',
12 => 'javelin-mask',
13 => 'javelin-typeahead',
14 => 'javelin-typeahead-normalizer',
15 => 'javelin-typeahead-source',
16 => 'javelin-typeahead-preloaded-source',
17 => 'javelin-typeahead-ondemand-source',
18 => 'javelin-tokenizer',
),
- 'uri' => '/res/pkg/1c6f020b/javelin.pkg.js',
+ 'uri' => '/res/pkg/d466c034/javelin.pkg.js',
'type' => 'js',
),
'e30a3fa8' =>
array(
'name' => 'maniphest.pkg.css',
'symbols' =>
array(
0 => 'maniphest-task-summary-css',
1 => 'maniphest-transaction-detail-css',
2 => 'aphront-attached-file-view-css',
3 => 'phabricator-project-tag-css',
),
'uri' => '/res/pkg/e30a3fa8/maniphest.pkg.css',
'type' => 'css',
),
'7707de41' =>
array(
'name' => 'maniphest.pkg.js',
'symbols' =>
array(
0 => 'javelin-behavior-maniphest-batch-selector',
1 => 'javelin-behavior-maniphest-transaction-controls',
2 => 'javelin-behavior-maniphest-transaction-preview',
3 => 'javelin-behavior-maniphest-transaction-expand',
4 => 'javelin-behavior-maniphest-subpriority-editor',
),
'uri' => '/res/pkg/7707de41/maniphest.pkg.js',
'type' => 'js',
),
),
'reverse' =>
array(
'aphront-attached-file-view-css' => 'e30a3fa8',
- 'aphront-crumbs-view-css' => '0e6165d0',
- 'aphront-dialog-view-css' => '0e6165d0',
- 'aphront-error-view-css' => '0e6165d0',
- 'aphront-form-view-css' => '0e6165d0',
- 'aphront-list-filter-view-css' => '0e6165d0',
- 'aphront-pager-view-css' => '0e6165d0',
- 'aphront-panel-view-css' => '0e6165d0',
- 'aphront-table-view-css' => '0e6165d0',
- 'aphront-tokenizer-control-css' => '0e6165d0',
- 'aphront-tooltip-css' => '0e6165d0',
- 'aphront-typeahead-control-css' => '0e6165d0',
+ 'aphront-crumbs-view-css' => '4b569463',
+ 'aphront-dialog-view-css' => '4b569463',
+ 'aphront-error-view-css' => '4b569463',
+ 'aphront-form-view-css' => '4b569463',
+ 'aphront-list-filter-view-css' => '4b569463',
+ 'aphront-pager-view-css' => '4b569463',
+ 'aphront-panel-view-css' => '4b569463',
+ 'aphront-table-view-css' => '4b569463',
+ 'aphront-tokenizer-control-css' => '4b569463',
+ 'aphront-tooltip-css' => '4b569463',
+ 'aphront-typeahead-control-css' => '4b569463',
'differential-changeset-view-css' => '8aaacd1b',
'differential-core-view-css' => '8aaacd1b',
- 'differential-inline-comment-editor' => '9dae5f20',
+ 'differential-inline-comment-editor' => '95d0d865',
'differential-local-commits-view-css' => '8aaacd1b',
'differential-results-table-css' => '8aaacd1b',
'differential-revision-add-comment-css' => '8aaacd1b',
'differential-revision-comment-css' => '8aaacd1b',
'differential-revision-comment-list-css' => '8aaacd1b',
'differential-revision-history-css' => '8aaacd1b',
'differential-revision-list-css' => '8aaacd1b',
'differential-table-of-contents-css' => '8aaacd1b',
'diffusion-commit-view-css' => 'c8ce2d88',
'diffusion-icons-css' => 'c8ce2d88',
- 'global-drag-and-drop-css' => '0e6165d0',
+ 'global-drag-and-drop-css' => '4b569463',
'inline-comment-summary-css' => '8aaacd1b',
- 'javelin-aphlict' => 'ff199687',
- 'javelin-behavior' => '1c6f020b',
- 'javelin-behavior-aphlict-dropdown' => 'ff199687',
- 'javelin-behavior-aphlict-listen' => 'ff199687',
- 'javelin-behavior-aphront-basic-tokenizer' => 'ff199687',
- 'javelin-behavior-aphront-drag-and-drop' => '9dae5f20',
- 'javelin-behavior-aphront-drag-and-drop-textarea' => '9dae5f20',
- 'javelin-behavior-aphront-form-disable-on-submit' => 'ff199687',
+ 'javelin-aphlict' => 'bc0774e5',
+ 'javelin-behavior' => 'd466c034',
+ 'javelin-behavior-aphlict-dropdown' => 'bc0774e5',
+ 'javelin-behavior-aphlict-listen' => 'bc0774e5',
+ 'javelin-behavior-aphront-basic-tokenizer' => 'bc0774e5',
+ 'javelin-behavior-aphront-drag-and-drop' => '95d0d865',
+ 'javelin-behavior-aphront-drag-and-drop-textarea' => '95d0d865',
+ 'javelin-behavior-aphront-form-disable-on-submit' => 'bc0774e5',
'javelin-behavior-audit-preview' => 'f96657b8',
- 'javelin-behavior-dark-console' => '74593df4',
- 'javelin-behavior-device' => 'ff199687',
- 'javelin-behavior-differential-accept-with-errors' => '9dae5f20',
- 'javelin-behavior-differential-add-reviewers-and-ccs' => '9dae5f20',
- 'javelin-behavior-differential-comment-jump' => '9dae5f20',
- 'javelin-behavior-differential-diff-radios' => '9dae5f20',
- 'javelin-behavior-differential-dropdown-menus' => '9dae5f20',
- 'javelin-behavior-differential-edit-inline-comments' => '9dae5f20',
- 'javelin-behavior-differential-feedback-preview' => '9dae5f20',
- 'javelin-behavior-differential-keyboard-navigation' => '9dae5f20',
- 'javelin-behavior-differential-populate' => '9dae5f20',
- 'javelin-behavior-differential-show-more' => '9dae5f20',
- 'javelin-behavior-differential-toggle-files' => '9dae5f20',
- 'javelin-behavior-differential-user-select' => '9dae5f20',
+ 'javelin-behavior-dark-console' => '3e0098ea',
+ 'javelin-behavior-device' => 'bc0774e5',
+ 'javelin-behavior-differential-accept-with-errors' => '95d0d865',
+ 'javelin-behavior-differential-add-reviewers-and-ccs' => '95d0d865',
+ 'javelin-behavior-differential-comment-jump' => '95d0d865',
+ 'javelin-behavior-differential-diff-radios' => '95d0d865',
+ 'javelin-behavior-differential-dropdown-menus' => '95d0d865',
+ 'javelin-behavior-differential-edit-inline-comments' => '95d0d865',
+ 'javelin-behavior-differential-feedback-preview' => '95d0d865',
+ 'javelin-behavior-differential-keyboard-navigation' => '95d0d865',
+ 'javelin-behavior-differential-populate' => '95d0d865',
+ 'javelin-behavior-differential-show-more' => '95d0d865',
+ 'javelin-behavior-differential-toggle-files' => '95d0d865',
+ 'javelin-behavior-differential-user-select' => '95d0d865',
'javelin-behavior-diffusion-commit-graph' => 'f96657b8',
'javelin-behavior-diffusion-pull-lastmodified' => 'f96657b8',
- 'javelin-behavior-error-log' => '74593df4',
- 'javelin-behavior-global-drag-and-drop' => 'ff199687',
- 'javelin-behavior-konami' => 'ff199687',
- 'javelin-behavior-lightbox-attachments' => 'ff199687',
+ 'javelin-behavior-error-log' => '3e0098ea',
+ 'javelin-behavior-global-drag-and-drop' => 'bc0774e5',
+ 'javelin-behavior-konami' => 'bc0774e5',
+ 'javelin-behavior-lightbox-attachments' => 'bc0774e5',
'javelin-behavior-maniphest-batch-selector' => '7707de41',
'javelin-behavior-maniphest-subpriority-editor' => '7707de41',
'javelin-behavior-maniphest-transaction-controls' => '7707de41',
'javelin-behavior-maniphest-transaction-expand' => '7707de41',
'javelin-behavior-maniphest-transaction-preview' => '7707de41',
- 'javelin-behavior-phabricator-active-nav' => 'ff199687',
- 'javelin-behavior-phabricator-autofocus' => 'ff199687',
- 'javelin-behavior-phabricator-home-reveal-tiles' => 'ff199687',
- 'javelin-behavior-phabricator-keyboard-shortcuts' => 'ff199687',
- 'javelin-behavior-phabricator-nav' => 'ff199687',
- 'javelin-behavior-phabricator-object-selector' => '9dae5f20',
- 'javelin-behavior-phabricator-oncopy' => 'ff199687',
- 'javelin-behavior-phabricator-remarkup-assist' => 'ff199687',
- 'javelin-behavior-phabricator-search-typeahead' => 'ff199687',
- 'javelin-behavior-phabricator-tooltips' => 'ff199687',
- 'javelin-behavior-phabricator-watch-anchor' => 'ff199687',
- 'javelin-behavior-refresh-csrf' => 'ff199687',
- 'javelin-behavior-repository-crossreference' => '9dae5f20',
- 'javelin-behavior-toggle-class' => 'ff199687',
- 'javelin-behavior-workflow' => 'ff199687',
- 'javelin-dom' => '1c6f020b',
- 'javelin-event' => '1c6f020b',
- 'javelin-install' => '1c6f020b',
- 'javelin-json' => '1c6f020b',
- 'javelin-mask' => '1c6f020b',
- 'javelin-request' => '1c6f020b',
- 'javelin-resource' => '1c6f020b',
- 'javelin-stratcom' => '1c6f020b',
- 'javelin-tokenizer' => '1c6f020b',
- 'javelin-typeahead' => '1c6f020b',
- 'javelin-typeahead-normalizer' => '1c6f020b',
- 'javelin-typeahead-ondemand-source' => '1c6f020b',
- 'javelin-typeahead-preloaded-source' => '1c6f020b',
- 'javelin-typeahead-source' => '1c6f020b',
- 'javelin-uri' => '1c6f020b',
- 'javelin-util' => '1c6f020b',
- 'javelin-vector' => '1c6f020b',
- 'javelin-workflow' => '1c6f020b',
- 'lightbox-attachment-css' => '0e6165d0',
+ 'javelin-behavior-phabricator-active-nav' => 'bc0774e5',
+ 'javelin-behavior-phabricator-autofocus' => 'bc0774e5',
+ 'javelin-behavior-phabricator-home-reveal-tiles' => 'bc0774e5',
+ 'javelin-behavior-phabricator-keyboard-shortcuts' => 'bc0774e5',
+ 'javelin-behavior-phabricator-nav' => 'bc0774e5',
+ 'javelin-behavior-phabricator-object-selector' => '95d0d865',
+ 'javelin-behavior-phabricator-oncopy' => 'bc0774e5',
+ 'javelin-behavior-phabricator-remarkup-assist' => 'bc0774e5',
+ 'javelin-behavior-phabricator-search-typeahead' => 'bc0774e5',
+ 'javelin-behavior-phabricator-tooltips' => 'bc0774e5',
+ 'javelin-behavior-phabricator-watch-anchor' => 'bc0774e5',
+ 'javelin-behavior-refresh-csrf' => 'bc0774e5',
+ 'javelin-behavior-repository-crossreference' => '95d0d865',
+ 'javelin-behavior-toggle-class' => 'bc0774e5',
+ 'javelin-behavior-workflow' => 'bc0774e5',
+ 'javelin-dom' => 'd466c034',
+ 'javelin-event' => 'd466c034',
+ 'javelin-install' => 'd466c034',
+ 'javelin-json' => 'd466c034',
+ 'javelin-mask' => 'd466c034',
+ 'javelin-request' => 'd466c034',
+ 'javelin-resource' => 'd466c034',
+ 'javelin-stratcom' => 'd466c034',
+ 'javelin-tokenizer' => 'd466c034',
+ 'javelin-typeahead' => 'd466c034',
+ 'javelin-typeahead-normalizer' => 'd466c034',
+ 'javelin-typeahead-ondemand-source' => 'd466c034',
+ 'javelin-typeahead-preloaded-source' => 'd466c034',
+ 'javelin-typeahead-source' => 'd466c034',
+ 'javelin-uri' => 'd466c034',
+ 'javelin-util' => 'd466c034',
+ 'javelin-vector' => 'd466c034',
+ 'javelin-workflow' => 'd466c034',
+ 'lightbox-attachment-css' => '4b569463',
'maniphest-task-summary-css' => 'e30a3fa8',
'maniphest-transaction-detail-css' => 'e30a3fa8',
- 'phabricator-busy' => 'ff199687',
+ 'phabricator-busy' => 'bc0774e5',
'phabricator-content-source-view-css' => '8aaacd1b',
- 'phabricator-core-buttons-css' => '0e6165d0',
- 'phabricator-core-css' => '0e6165d0',
- 'phabricator-crumbs-view-css' => '0e6165d0',
- 'phabricator-directory-css' => '0e6165d0',
- 'phabricator-drag-and-drop-file-upload' => '9dae5f20',
- 'phabricator-dropdown-menu' => 'ff199687',
- 'phabricator-file-upload' => 'ff199687',
- 'phabricator-filetree-view-css' => '0e6165d0',
- 'phabricator-flag-css' => '0e6165d0',
- 'phabricator-form-view-css' => '0e6165d0',
- 'phabricator-header-view-css' => '0e6165d0',
- 'phabricator-jump-nav' => '0e6165d0',
- 'phabricator-keyboard-shortcut' => 'ff199687',
- 'phabricator-keyboard-shortcut-manager' => 'ff199687',
- 'phabricator-main-menu-view' => '0e6165d0',
- 'phabricator-menu-item' => 'ff199687',
- 'phabricator-nav-view-css' => '0e6165d0',
- 'phabricator-notification' => 'ff199687',
- 'phabricator-notification-css' => '0e6165d0',
- 'phabricator-notification-menu-css' => '0e6165d0',
- 'phabricator-object-item-list-view-css' => '0e6165d0',
+ 'phabricator-core-buttons-css' => '4b569463',
+ 'phabricator-core-css' => '4b569463',
+ 'phabricator-crumbs-view-css' => '4b569463',
+ 'phabricator-directory-css' => '4b569463',
+ 'phabricator-drag-and-drop-file-upload' => '95d0d865',
+ 'phabricator-dropdown-menu' => 'bc0774e5',
+ 'phabricator-file-upload' => 'bc0774e5',
+ 'phabricator-filetree-view-css' => '4b569463',
+ 'phabricator-flag-css' => '4b569463',
+ 'phabricator-form-view-css' => '4b569463',
+ 'phabricator-header-view-css' => '4b569463',
+ 'phabricator-jump-nav' => '4b569463',
+ 'phabricator-keyboard-shortcut' => 'bc0774e5',
+ 'phabricator-keyboard-shortcut-manager' => 'bc0774e5',
+ 'phabricator-main-menu-view' => '4b569463',
+ 'phabricator-menu-item' => 'bc0774e5',
+ 'phabricator-nav-view-css' => '4b569463',
+ 'phabricator-notification' => 'bc0774e5',
+ 'phabricator-notification-css' => '4b569463',
+ 'phabricator-notification-menu-css' => '4b569463',
+ 'phabricator-object-item-list-view-css' => '4b569463',
'phabricator-object-selector-css' => '8aaacd1b',
- 'phabricator-paste-file-upload' => 'ff199687',
- 'phabricator-prefab' => 'ff199687',
+ 'phabricator-paste-file-upload' => 'bc0774e5',
+ 'phabricator-prefab' => 'bc0774e5',
'phabricator-project-tag-css' => 'e30a3fa8',
- 'phabricator-remarkup-css' => '0e6165d0',
- 'phabricator-shaped-request' => '9dae5f20',
- 'phabricator-side-menu-view-css' => '0e6165d0',
- 'phabricator-standard-page-view' => '0e6165d0',
- 'phabricator-textareautils' => 'ff199687',
- 'phabricator-tooltip' => 'ff199687',
- 'phabricator-transaction-view-css' => '0e6165d0',
- 'phabricator-zindex-css' => '0e6165d0',
- 'sprite-apps-large-css' => '0e6165d0',
- 'sprite-gradient-css' => '0e6165d0',
- 'sprite-icon-css' => '0e6165d0',
- 'sprite-menu-css' => '0e6165d0',
- 'syntax-highlighting-css' => '0e6165d0',
+ 'phabricator-remarkup-css' => '4b569463',
+ 'phabricator-shaped-request' => '95d0d865',
+ 'phabricator-side-menu-view-css' => '4b569463',
+ 'phabricator-standard-page-view' => '4b569463',
+ 'phabricator-textareautils' => 'bc0774e5',
+ 'phabricator-tooltip' => 'bc0774e5',
+ 'phabricator-transaction-view-css' => '4b569463',
+ 'phabricator-zindex-css' => '4b569463',
+ 'sprite-apps-large-css' => '4b569463',
+ 'sprite-gradient-css' => '4b569463',
+ 'sprite-icon-css' => '4b569463',
+ 'sprite-menu-css' => '4b569463',
+ 'syntax-highlighting-css' => '4b569463',
),
));
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index c9e7a4dd43..a81f53697f 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1,2904 +1,2935 @@
<?php
/**
* This file is automatically generated. Use 'arc liberate' to rebuild it.
* @generated
* @phutil-library-version 2
*/
phutil_register_library_map(array(
'__library_version__' => 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',
+ 'AphrontFormCropControl' => 'view/form/control/AphrontFormCropControl.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',
+ 'AuditPeopleMenuEventListener' => 'applications/audit/events/AuditPeopleMenuEventListener.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',
+ 'ConpherenceFormDragAndDropUploadControl' => 'applications/conpherence/view/ConpherenceFormDragAndDropUploadControl.php',
+ 'ConpherenceImageData' => 'applications/conpherence/constants/ConpherenceImageData.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',
+ 'ConpherencePeopleMenuEventListener' => 'applications/conpherence/events/ConpherencePeopleMenuEventListener.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',
+ 'DifferentialPeopleMenuEventListener' => 'applications/differential/events/DifferentialPeopleMenuEventListener.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',
+ 'DiffusionPeopleMenuEventListener' => 'applications/diffusion/events/DiffusionPeopleMenuEventListener.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',
+ 'ManiphestPeopleMenuEventListener' => 'applications/maniphest/event/ManiphestPeopleMenuEventListener.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',
+ 'PhabricatorBaseProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorBaseProtocolAdapter.php',
+ 'PhabricatorBot' => 'infrastructure/daemon/bot/PhabricatorBot.php',
+ 'PhabricatorBotDebugLogHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotDebugLogHandler.php',
+ 'PhabricatorBotDifferentialNotificationHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotDifferentialNotificationHandler.php',
+ 'PhabricatorBotFeedNotificationHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotFeedNotificationHandler.php',
+ 'PhabricatorBotHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotHandler.php',
+ 'PhabricatorBotLogHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotLogHandler.php',
+ 'PhabricatorBotMacroHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotMacroHandler.php',
+ 'PhabricatorBotMessage' => 'infrastructure/daemon/bot/PhabricatorBotMessage.php',
+ 'PhabricatorBotObjectNameHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php',
+ 'PhabricatorBotSymbolHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotSymbolHandler.php',
+ 'PhabricatorBotWhatsNewHandler' => 'infrastructure/daemon/bot/handler/PhabricatorBotWhatsNewHandler.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',
+ 'PhabricatorCampfireProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorCampfireProtocolAdapter.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',
+ 'PhabricatorFileTestCase' => 'applications/files/storage/__tests__/PhabricatorFileTestCase.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',
+ 'PhabricatorIRCBot' => 'infrastructure/daemon/bot/PhabricatorIRCBot.php',
+ 'PhabricatorIRCProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorIRCProtocolAdapter.php',
+ 'PhabricatorIRCProtocolHandler' => 'infrastructure/daemon/bot/handler/PhabricatorIRCProtocolHandler.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',
'PhabricatorSettingsPanelDiffPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDiffPreferences.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',
+ 'PhabricatorTestStorageEngine' => 'applications/files/engine/PhabricatorTestStorageEngine.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',
+ 'PholioInlineSaveController' => 'applications/pholio/controller/PholioInlineSaveController.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',
+ 'AphrontFormCropControl' => 'AphrontFormControl',
'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',
+ 'AuditPeopleMenuEventListener' => 'PhutilEventListener',
'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',
+ 'ConpherenceFormDragAndDropUploadControl' => 'AphrontFormControl',
+ 'ConpherenceImageData' => 'ConpherenceConstants',
'ConpherenceListController' => 'ConpherenceController',
'ConpherenceMenuItemView' => 'AphrontTagView',
'ConpherenceNewController' => 'ConpherenceController',
'ConpherenceParticipant' => 'ConpherenceDAO',
'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery',
'ConpherenceParticipationStatus' => 'ConpherenceConstants',
+ 'ConpherencePeopleMenuEventListener' => 'PhutilEventListener',
'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',
+ 'DifferentialPeopleMenuEventListener' => 'PhutilEventListener',
'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',
+ 'DiffusionPeopleMenuEventListener' => 'PhutilEventListener',
'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',
+ 'ManiphestPeopleMenuEventListener' => 'PhutilEventListener',
'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',
+ 'PhabricatorBot' => 'PhabricatorDaemon',
+ 'PhabricatorBotDebugLogHandler' => 'PhabricatorBotHandler',
+ 'PhabricatorBotDifferentialNotificationHandler' => 'PhabricatorBotHandler',
+ 'PhabricatorBotFeedNotificationHandler' => 'PhabricatorBotHandler',
+ 'PhabricatorBotLogHandler' => 'PhabricatorBotHandler',
+ 'PhabricatorBotMacroHandler' => 'PhabricatorBotHandler',
+ 'PhabricatorBotObjectNameHandler' => 'PhabricatorBotHandler',
+ 'PhabricatorBotSymbolHandler' => 'PhabricatorBotHandler',
+ 'PhabricatorBotWhatsNewHandler' => 'PhabricatorBotHandler',
'PhabricatorBuiltinPatchList' => 'PhabricatorSQLPatchList',
'PhabricatorButtonsExample' => 'PhabricatorUIExample',
'PhabricatorCacheDAO' => 'PhabricatorLiskDAO',
'PhabricatorCalendarBrowseController' => 'PhabricatorCalendarController',
'PhabricatorCalendarController' => 'PhabricatorController',
'PhabricatorCalendarDAO' => 'PhabricatorLiskDAO',
'PhabricatorCalendarDeleteStatusController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEditStatusController' => 'PhabricatorCalendarController',
'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO',
'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase',
'PhabricatorCalendarViewStatusController' => 'PhabricatorCalendarController',
+ 'PhabricatorCampfireProtocolAdapter' => 'PhabricatorBaseProtocolAdapter',
'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',
+ 'PhabricatorFileTestCase' => 'PhabricatorTestCase',
'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',
+ 'PhabricatorIRCProtocolAdapter' => 'PhabricatorBaseProtocolAdapter',
+ 'PhabricatorIRCProtocolHandler' => 'PhabricatorBotHandler',
'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',
'PhabricatorSettingsPanelDiffPreferences' => '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',
+ 'PhabricatorTestStorageEngine' => 'PhabricatorFileStorageEngine',
'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',
),
+ 'PholioInlineSaveController' => 'PholioController',
'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/applications/audit/application/PhabricatorApplicationAudit.php b/src/applications/audit/application/PhabricatorApplicationAudit.php
index d24e3a71a0..73ad9a2be3 100644
--- a/src/applications/audit/application/PhabricatorApplicationAudit.php
+++ b/src/applications/audit/application/PhabricatorApplicationAudit.php
@@ -1,80 +1,86 @@
<?php
final class PhabricatorApplicationAudit extends PhabricatorApplication {
public function getShortDescription() {
return pht('Audit Code');
}
public function getBaseURI() {
return '/audit/';
}
public function getIconName() {
return 'audit';
}
public function getHelpURI() {
return PhabricatorEnv::getDoclink('article/Audit_User_Guide.html');
}
+ public function getEventListeners() {
+ return array(
+ new AuditPeopleMenuEventListener()
+ );
+ }
+
public function getRoutes() {
return array(
'/audit/' => array(
'' => 'PhabricatorAuditListController',
'view/(?P<filter>[^/]+)/(?:(?P<name>[^/]+)/)?'
=> 'PhabricatorAuditListController',
'addcomment/' => 'PhabricatorAuditAddCommentController',
'preview/(?P<id>[1-9]\d*)/' => 'PhabricatorAuditPreviewController',
),
);
}
public function getApplicationGroup() {
return self::GROUP_CORE;
}
public function getApplicationOrder() {
return 0.130;
}
public function loadStatus(PhabricatorUser $user) {
$status = array();
$phids = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($user);
$audits = id(new PhabricatorAuditQuery())
->withAuditorPHIDs($phids)
->withStatus(PhabricatorAuditQuery::STATUS_OPEN)
->withAwaitingUser($user)
->execute();
$count = count($audits);
$type = $count
? PhabricatorApplicationStatusView::TYPE_INFO
: PhabricatorApplicationStatusView::TYPE_EMPTY;
$status[] = id(new PhabricatorApplicationStatusView())
->setType($type)
->setText(pht('%d Commit(s) Awaiting Audit', $count))
->setCount($count);
$commits = id(new PhabricatorAuditCommitQuery())
->withAuthorPHIDs($phids)
->withStatus(PhabricatorAuditQuery::STATUS_OPEN)
->execute();
$count = count($commits);
$type = $count
? PhabricatorApplicationStatusView::TYPE_NEEDS_ATTENTION
: PhabricatorApplicationStatusView::TYPE_EMPTY;
$status[] = id(new PhabricatorApplicationStatusView())
->setType($type)
->setText(pht('%d Problem Commit(s)', $count))
->setCount($count);
return $status;
}
}
diff --git a/src/applications/audit/events/AuditPeopleMenuEventListener.php b/src/applications/audit/events/AuditPeopleMenuEventListener.php
new file mode 100644
index 0000000000..3ab4b7739f
--- /dev/null
+++ b/src/applications/audit/events/AuditPeopleMenuEventListener.php
@@ -0,0 +1,38 @@
+<?php
+
+final class AuditPeopleMenuEventListener extends PhutilEventListener {
+
+ public function register() {
+ $this->listen(PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU);
+ }
+
+ public function handleEvent(PhutilEvent $event) {
+ switch ($event->getType()) {
+ case PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU:
+ $this->handleMenuEvent($event);
+ break;
+ }
+ }
+
+ private function handleMenuEvent($event) {
+ $viewer = $event->getUser();
+ $menu = $event->getValue('menu');
+ $person = $event->getValue('person');
+ $username = phutil_escape_uri($person->getUsername());
+
+ $href = '/audit/view/author/'.$username.'/';
+ $name = pht('Commits');
+
+ $menu->addMenuItemToLabel('activity',
+ id(new PhabricatorMenuItemView())
+ ->setIsExternal(true)
+ ->setName($name)
+ ->setHref($href)
+ ->setKey($name)
+ );
+
+ $event->setValue('menu', $menu);
+ }
+
+}
+
diff --git a/src/applications/config/check/PhabricatorSetupCheckDatabase.php b/src/applications/config/check/PhabricatorSetupCheckDatabase.php
index b4e19e2a0f..d966b19b97 100644
--- a/src/applications/config/check/PhabricatorSetupCheckDatabase.php
+++ b/src/applications/config/check/PhabricatorSetupCheckDatabase.php
@@ -1,99 +1,85 @@
<?php
final class PhabricatorSetupCheckDatabase extends PhabricatorSetupCheck {
public function getExecutionOrder() {
// This must run after basic PHP checks, but before most other checks.
return 0.5;
}
protected function executeChecks() {
$conf = PhabricatorEnv::newObjectFromConfig('mysql.configuration-provider');
$conn_user = $conf->getUser();
$conn_pass = $conf->getPassword();
$conn_host = $conf->getHost();
ini_set('mysql.connect_timeout', 2);
$conn_raw = PhabricatorEnv::newObjectFromConfig(
'mysql.implementation',
array(
array(
'user' => $conn_user,
'pass' => $conn_pass,
'host' => $conn_host,
'database' => null,
),
));
try {
queryfx($conn_raw, 'SELECT 1');
} catch (AphrontQueryConnectionException $ex) {
$message = pht(
"Unable to connect to MySQL!\n\n".
"%s\n\n".
"Make sure Phabricator and MySQL are correctly configured.",
$ex->getMessage());
$this->newIssue('mysql.connect')
->setName(pht('Can Not Connect to MySQL'))
->setMessage($message)
->setIsFatal(true)
->addPhabricatorConfig('mysql.host')
->addPhabricatorConfig('mysql.user')
->addPhabricatorConfig('mysql.pass');
return;
}
$engines = queryfx_all($conn_raw, 'SHOW ENGINES');
$engines = ipull($engines, 'Support', 'Engine');
$innodb = idx($engines, 'InnoDB');
if ($innodb != 'YES' && $innodb != 'DEFAULT') {
$message = pht(
"The 'InnoDB' engine is not available in MySQL. Enable InnoDB in ".
"your MySQL configuration.".
"\n\n".
"(If you aleady created tables, MySQL incorrectly used some other ".
"engine to create them. You need to convert them or drop and ".
"reinitialize them.)");
$this->newIssue('mysql.innodb')
->setName(pht('MySQL InnoDB Engine Not Available'))
->setMessage($message)
->setIsFatal(true);
return;
}
- if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) {
- $mode_string = queryfx_one($conn_raw, "SELECT @@sql_mode");
- $modes = explode(',', $mode_string['@@sql_mode']);
- if (!in_array('STRICT_ALL_TABLES', $modes)) {
- $message = pht(
- "The global sql_mode is not set to 'STRICT_ALL_TABLES'. It is ".
- "recommended that you set this mode while developing Phabricator.");
-
- $this->newIssue('mysql.mode')
- ->setName(pht('MySQL STRICT_ALL_TABLES mode not set.'))
- ->setMessage($message);
- }
- }
-
$namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace');
$databases = queryfx_all($conn_raw, 'SHOW DATABASES');
$databases = ipull($databases, 'Database', 'Database');
if (empty($databases[$namespace.'_meta_data'])) {
$message = pht(
'Run the storage upgrade script to setup Phabricator\'s database '.
'schema.');
$this->newIssue('storage.upgrade')
->setName(pht('Setup MySQL Schema'))
->setMessage($message)
->setIsFatal(true)
->addCommand(hsprintf('<tt>phabricator/ $</tt> ./bin/storage upgrade'));
}
}
}
diff --git a/src/applications/config/check/PhabricatorSetupCheckMySQL.php b/src/applications/config/check/PhabricatorSetupCheckMySQL.php
index e8de03bb51..cabb822e81 100644
--- a/src/applications/config/check/PhabricatorSetupCheckMySQL.php
+++ b/src/applications/config/check/PhabricatorSetupCheckMySQL.php
@@ -1,29 +1,54 @@
<?php
final class PhabricatorSetupCheckMySQL extends PhabricatorSetupCheck {
protected function executeChecks() {
$conn_raw = id(new PhabricatorUser())->establishConnection('w');
$max_allowed_packet = queryfx_one(
$conn_raw,
'SHOW VARIABLES LIKE %s',
'max_allowed_packet');
$max_allowed_packet = idx($max_allowed_packet, 'Value', PHP_INT_MAX);
$recommended_minimum = 1024 * 1024;
if ($max_allowed_packet < $recommended_minimum) {
$message = pht(
"MySQL is configured with a very small 'max_allowed_packet' (%d), ".
"which may cause some large writes to fail. Strongly consider raising ".
"this to at least %d in your MySQL configuration.",
$max_allowed_packet,
$recommended_minimum);
$this->newIssue('mysql.max_allowed_packet')
->setName(pht('Small MySQL "max_allowed_packet"'))
->setMessage($message);
}
+
+ if (PhabricatorEnv::getEnvConfig('phabricator.developer-mode')) {
+ $mode_string = queryfx_one($conn_raw, "SELECT @@sql_mode");
+ $modes = explode(',', $mode_string['@@sql_mode']);
+ if (!in_array('STRICT_ALL_TABLES', $modes)) {
+ $summary = pht(
+ "MySQL is not in strict mode, but should be for Phabricator ".
+ "development.");
+
+ $message = pht(
+ "This install is in developer mode, but the global sql_mode is not ".
+ "set to 'STRICT_ALL_TABLES'. It is recommended that you set this ".
+ "mode while developing Phabricator. Strict mode will promote some ".
+ "query warnings to errors, and ensure you don't miss them during ".
+ "development. You can find more information about this mode (and ".
+ "how to configure it) in the MySQL manual.");
+
+ $this->newIssue('mysql.mode')
+ ->setName(pht('MySQL STRICT_ALL_TABLES Mode Not Set'))
+ ->addPhabricatorConfig('phabricator.developer-mode')
+ ->setSummary($summary)
+ ->setMessage($message);
+ }
+ }
+
}
}
diff --git a/src/applications/conpherence/application/PhabricatorApplicationConpherence.php b/src/applications/conpherence/application/PhabricatorApplicationConpherence.php
index 71e7fb1b9f..9f78872453 100644
--- a/src/applications/conpherence/application/PhabricatorApplicationConpherence.php
+++ b/src/applications/conpherence/application/PhabricatorApplicationConpherence.php
@@ -1,48 +1,54 @@
<?php
/**
* @group conpherence
*/
final class PhabricatorApplicationConpherence extends PhabricatorApplication {
public function isBeta() {
return true;
}
public function getBaseURI() {
return '/conpherence/';
}
public function getQuickCreateURI() {
return $this->getBaseURI().'new/';
}
public function getShortDescription() {
return pht('Messaging');
}
public function getIconName() {
return 'conpherence';
}
public function getTitleGlyph() {
return "\xE2\x98\x8E";
}
public function getApplicationGroup() {
return self::GROUP_COMMUNICATION;
}
+ public function getEventListeners() {
+ return array(
+ new ConpherencePeopleMenuEventListener(),
+ );
+ }
+
public function getRoutes() {
return array(
'/conpherence/' => array(
'' => 'ConpherenceListController',
'new/' => 'ConpherenceNewController',
'view/(?P<id>[1-9]\d*)/' => 'ConpherenceViewController',
'update/(?P<id>[1-9]\d*)/' => 'ConpherenceUpdateController',
'(?P<id>[1-9]\d*)/' => 'ConpherenceListController',
),
);
}
}
diff --git a/src/applications/conpherence/constants/ConpherenceImageData.php b/src/applications/conpherence/constants/ConpherenceImageData.php
new file mode 100644
index 0000000000..618acb4b35
--- /dev/null
+++ b/src/applications/conpherence/constants/ConpherenceImageData.php
@@ -0,0 +1,11 @@
+<?php
+
+final class ConpherenceImageData extends ConpherenceConstants {
+
+ const SIZE_ORIG = 'original';
+ const SIZE_HEAD = 'header';
+
+ const HEAD_WIDTH = 120;
+ const HEAD_HEIGHT = 80;
+
+}
diff --git a/src/applications/conpherence/constants/ConpherenceTransactionType.php b/src/applications/conpherence/constants/ConpherenceTransactionType.php
index b42af302f1..7ccf559312 100644
--- a/src/applications/conpherence/constants/ConpherenceTransactionType.php
+++ b/src/applications/conpherence/constants/ConpherenceTransactionType.php
@@ -1,13 +1,14 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceTransactionType extends ConpherenceConstants {
const TYPE_FILES = 'files';
const TYPE_TITLE = 'title';
const TYPE_PICTURE = 'picture';
+ const TYPE_PICTURE_CROP = 'picture-crop';
const TYPE_PARTICIPANTS = 'participants';
}
diff --git a/src/applications/conpherence/controller/ConpherenceController.php b/src/applications/conpherence/controller/ConpherenceController.php
index 3050ceb224..006049b9c7 100644
--- a/src/applications/conpherence/controller/ConpherenceController.php
+++ b/src/applications/conpherence/controller/ConpherenceController.php
@@ -1,224 +1,236 @@
<?php
/**
* @group conpherence
*/
abstract class ConpherenceController extends PhabricatorController {
private $conpherences;
private $selectedConpherencePHID;
private $readConpherences;
private $unreadConpherences;
public function setUnreadConpherences(array $conpherences) {
assert_instances_of($conpherences, 'ConpherenceThread');
$this->unreadConpherences = $conpherences;
return $this;
}
public function getUnreadConpherences() {
return $this->unreadConpherences;
}
public function setReadConpherences(array $conpherences) {
assert_instances_of($conpherences, 'ConpherenceThread');
$this->readConpherences = $conpherences;
return $this;
}
public function getReadConpherences() {
return $this->readConpherences;
}
public function setSelectedConpherencePHID($phid) {
$this->selectedConpherencePHID = $phid;
return $this;
}
public function getSelectedConpherencePHID() {
return $this->selectedConpherencePHID;
}
/**
* Try for a full set of unread conpherences, and if we fail
* load read conpherences. Additional conpherences in either category
* are loaded asynchronously.
*/
public function loadStartingConpherences($current_selection_epoch = null) {
$user = $this->getRequest()->getUser();
$read_participant_query = id(new ConpherenceParticipantQuery())
->withParticipantPHIDs(array($user->getPHID()));
$read_status = ConpherenceParticipationStatus::UP_TO_DATE;
if ($current_selection_epoch) {
$read_one = $read_participant_query
->withParticipationStatus($read_status)
->withDateTouched($current_selection_epoch, '>')
->execute();
$read_two = $read_participant_query
->withDateTouched($current_selection_epoch, '<=')
->execute();
$read = array_merge($read_one, $read_two);
} else {
$read = $read_participant_query
->withParticipationStatus($read_status)
->execute();
}
$unread_status = ConpherenceParticipationStatus::BEHIND;
$unread = id(new ConpherenceParticipantQuery())
->withParticipantPHIDs(array($user->getPHID()))
->withParticipationStatus($unread_status)
->execute();
$all_participation = $unread + $read;
$all_conpherence_phids = array_keys($all_participation);
$all_conpherences = id(new ConpherenceThreadQuery())
->setViewer($user)
->withPHIDs($all_conpherence_phids)
->execute();
$unread_conpherences = array_select_keys(
$all_conpherences,
array_keys($unread)
);
$this->setUnreadConpherences($unread_conpherences);
$read_conpherences = array_select_keys(
$all_conpherences,
array_keys($read)
);
$this->setReadConpherences($read_conpherences);
if (!$this->getSelectedConpherencePHID()) {
$this->setSelectedConpherencePHID(reset($all_conpherence_phids));
}
return $this;
}
public function buildSideNavView($filter = null) {
require_celerity_resource('conpherence-menu-css');
$unread_conpherences = $this->getUnreadConpherences();
$read_conpherences = $this->getReadConpherences();
$user = $this->getRequest()->getUser();
$menu = new PhabricatorMenuView();
$nav = AphrontSideNavFilterView::newFromMenu($menu);
$nav->addClass('conpherence-menu');
$nav->setMenuID('conpherence-menu');
$nav->addButton(
'new',
pht('New Conversation'),
$this->getApplicationURI('new/')
);
$nav->addLabel(pht('Unread'));
$nav = $this->addConpherencesToNav($unread_conpherences, $nav);
$nav->addLabel(pht('Read'));
$nav = $this->addConpherencesToNav($read_conpherences, $nav, true);
$nav->selectFilter($filter);
return $nav;
}
private function addConpherencesToNav(
array $conpherences,
AphrontSideNavFilterView $nav,
$read = false) {
$user = $this->getRequest()->getUser();
foreach ($conpherences as $conpherence) {
$uri = $this->getApplicationURI('view/'.$conpherence->getID().'/');
- $data = $conpherence->getDisplayData($user);
+ $data = $conpherence->getDisplayData(
+ $user,
+ null
+ );
$title = $data['title'];
$subtitle = $data['subtitle'];
$unread_count = $data['unread_count'];
$epoch = $data['epoch'];
$image = $data['image'];
$snippet = $data['snippet'];
$item = id(new ConpherenceMenuItemView())
->setUser($user)
->setTitle($title)
->setSubtitle($subtitle)
->setHref($uri)
->setEpoch($epoch)
->setImageURI($image)
->setMessageText($snippet)
->setUnreadCount($unread_count)
->setID($conpherence->getPHID())
->addSigil('conpherence-menu-click')
->setMetadata(array('id' => $conpherence->getID()));
if ($this->getSelectedConpherencePHID() == $conpherence->getPHID()) {
$item->addClass('conpherence-selected');
$item->addClass('hide-unread-count');
}
// TODO: [HTML] Clean this up when we clean up HTML stuff in Conpherence.
$nav->addCustomBlock(phutil_safe_html($item->render()));
}
if (empty($conpherences) || $read) {
$nav->addCustomBlock($this->getNoConpherencesBlock());
}
return $nav;
}
private function getNoConpherencesBlock() {
return phutil_tag(
'div',
array(
'class' => 'no-conpherences-menu-item'
),
pht('No more conpherences.'));
}
public function buildApplicationMenu() {
return $this->buildSideNavView()->getMenu();
}
public function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$crumbs
->addAction(
id(new PhabricatorMenuItemView())
->setName(pht('New Conversation'))
->setHref($this->getApplicationURI('new/'))
->setIcon('create')
)
->addCrumb(
id(new PhabricatorCrumbView())
->setName(pht('Conpherence'))
);
return $crumbs;
}
protected function initJavelinBehaviors() {
Javelin::initBehavior('conpherence-menu',
array(
'base_uri' => $this->getApplicationURI(''),
'header' => 'conpherence-header-pane',
'messages' => 'conpherence-messages',
'widgets_pane' => 'conpherence-widget-pane',
'form_pane' => 'conpherence-form',
+ 'menu_pane' => 'conpherence-menu',
'fancy_ajax' => (bool) $this->getSelectedConpherencePHID()
)
);
Javelin::initBehavior('conpherence-init',
array(
'selected_conpherence_id' => $this->getSelectedConpherencePHID(),
'menu_pane' => 'conpherence-menu',
'messages_pane' => 'conpherence-message-pane',
'messages' => 'conpherence-messages',
'widgets_pane' => 'conpherence-widget-pane',
'form_pane' => 'conpherence-form'
)
);
+ Javelin::initBehavior('conpherence-drag-and-drop-photo',
+ array(
+ 'target' => 'conpherence-header-pane',
+ 'form_pane' => 'conpherence-form',
+ 'upload_uri' => '/file/dropupload/',
+ 'activated_class' => 'conpherence-header-upload-photo',
+ )
+ );
}
}
diff --git a/src/applications/conpherence/controller/ConpherenceUpdateController.php b/src/applications/conpherence/controller/ConpherenceUpdateController.php
index 2d8deee715..ad3bf86fa1 100644
--- a/src/applications/conpherence/controller/ConpherenceUpdateController.php
+++ b/src/applications/conpherence/controller/ConpherenceUpdateController.php
@@ -1,168 +1,220 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceUpdateController extends
ConpherenceController {
private $conpherenceID;
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();
}
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($user)
->withIDs(array($conpherence_id))
+ ->needOrigPics(true)
+ ->needHeaderPics(true)
->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
);
break;
case 'metadata':
$xactions = array();
- $images = $request->getArr('image');
- if ($images) {
- // just take the first one
- $file_phid = reset($images);
- $file = id(new PhabricatorFileQuery())
+ $top = $request->getInt('image_y');
+ $left = $request->getInt('image_x');
+ $file_id = $request->getInt('file_id');
+ if ($file_id) {
+ $orig_file = id(new PhabricatorFileQuery())
->setViewer($user)
- ->withPHIDs(array($file_phid))
+ ->withIDs(array($file_id))
->executeOne();
- $okay = $file->isTransformableImage();
+ $okay = $orig_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);
+ ->setNewValue($orig_file->getPHID());
+ // do 2 transformations "crudely"
+ $xformer = new PhabricatorImageTransformer();
+ $header_file = $xformer->executeConpherenceTransform(
+ $orig_file,
+ 0,
+ 0,
+ ConpherenceImageData::HEAD_WIDTH,
+ ConpherenceImageData::HEAD_HEIGHT
+ );
+ // this is handled outside the editor for now. no particularly
+ // good reason to move it inside
+ $conpherence->setImagePHIDs(
+ array(
+ ConpherenceImageData::SIZE_HEAD => $header_file->getPHID(),
+ )
+ );
+ $conpherence->setImages(
+ array(
+ ConpherenceImageData::SIZE_HEAD => $header_file,
+ )
+ );
} else {
- $e_file[] = $file;
+ $e_file[] = $orig_file;
$errors[] =
pht('This server only supports these image formats: %s.',
implode(', ', $supported_formats));
}
+ } else if ($top !== null || $left !== null) {
+ $file = $conpherence->getImage(ConpherenceImageData::SIZE_ORIG);
+ $xformer = new PhabricatorImageTransformer();
+ $xformed = $xformer->executeConpherenceTransform(
+ $file,
+ $top,
+ $left,
+ ConpherenceImageData::HEAD_WIDTH,
+ ConpherenceImageData::HEAD_HEIGHT
+ );
+ $image_phid = $xformed->getPHID();
+
+ $xactions[] = id(new ConpherenceTransaction())
+ ->setTransactionType(
+ ConpherenceTransactionType::TYPE_PICTURE_CROP
+ )
+ ->setNewValue($image_phid);
}
$title = $request->getStr('title');
if ($title != $conpherence->getTitle()) {
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(ConpherenceTransactionType::TYPE_TITLE)
->setNewValue($title);
}
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))
+ );
+
+ $image = $conpherence->getImage(ConpherenceImageData::SIZE_ORIG);
+ if ($image) {
+ $form
+ ->appendChild(
+ id(new AphrontFormMarkupControl())
+ ->setLabel(pht('Image'))
+ ->setValue(phutil_tag(
+ 'img',
+ array(
+ 'src' =>
+ $conpherence->loadImageURI(ConpherenceImageData::SIZE_HEAD),
+ ))
+ )
+ )
+ ->appendChild(
+ id(new AphrontFormCropControl())
+ ->setLabel(pht('Crop Image'))
+ ->setValue($image)
+ ->setWidth(ConpherenceImageData::HEAD_WIDTH)
+ ->setHeight(ConpherenceImageData::HEAD_HEIGHT)
+ )
+ ->appendChild(
+ id(new ConpherenceFormDragAndDropUploadControl())
+ ->setLabel(pht('Change Image'))
+ );
+
+ } else {
+
+ $form
+ ->appendChild(
+ id(new ConpherenceFormDragAndDropUploadControl())
+ ->setLabel(pht('Image'))
);
+ }
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 e272f871f3..66f80ba133 100644
--- a/src/applications/conpherence/controller/ConpherenceViewController.php
+++ b/src/applications/conpherence/controller/ConpherenceViewController.php
@@ -1,412 +1,437 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceViewController extends
ConpherenceController {
private $conpherenceID;
private $conpherence;
public function setConpherence(ConpherenceThread $conpherence) {
$this->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)
+ ->needHeaderPics(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);
+ $display_data = $conpherence->getDisplayData(
+ $user,
+ ConpherenceImageData::SIZE_HEAD
+ );
$edit_href = $this->getApplicationURI('update/'.$conpherence->getID().'/');
+ $class_mod = $display_data['image_class'];
$header =
+ phutil_tag(
+ 'div',
+ array(
+ 'class' => 'upload-photo'
+ ),
+ pht('Drop photo here to change this Conpherence photo.')
+ ).
javelin_tag(
'a',
array(
'class' => 'edit',
'href' => $edit_href,
- 'sigil' => 'workflow',
+ 'sigil' => 'workflow edit-action',
),
''
).
phutil_tag(
'div',
array(
- 'class' => 'header-image',
+ 'class' => $class_mod.'header-image',
'style' => 'background-image: url('.$display_data['image'].');'
),
''
).
phutil_tag(
'div',
array(
- 'class' => 'title',
+ 'class' => $class_mod.'title',
),
$display_data['title']
).
phutil_tag(
'div',
array(
- 'class' => 'subtitle',
+ 'class' => $class_mod.'subtitle',
),
$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();
+
+ $engine = id(new PhabricatorMarkupEngine())
+ ->setViewer($user);
+ foreach ($transactions as $transaction) {
+ if ($transaction->getComment()) {
+ $engine->addObject(
+ $transaction->getComment(),
+ PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
+ }
+ }
+ $engine->process();
+
foreach ($transactions as $transaction) {
if ($transaction->shouldHide()) {
continue;
}
$rendered_transactions[] = id(new ConpherenceTransactionView())
->setUser($user)
->setConpherenceTransaction($transaction)
->setHandles($handles)
+ ->setMarkupEngine($engine)
->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');
require_celerity_resource('sprite-conpher-css');
Javelin::initBehavior(
'conpherence-widget-pane',
array(
'widgetRegistery' => array(
'widgets-files' => 1,
'widgets-tasks' => 1,
'widgets-calendar' => 1,
)
)
);
$conpherence = $this->getConpherence();
$widgets = phutil_tag(
'div',
array(
'class' => 'widgets-header'
),
array(
javelin_tag(
'a',
array(
'sigil' => 'conpherence-change-widget',
'meta' => array(
'widget' => 'widgets-files',
'toggleClass' => 'conpher_files_on'
),
'id' => 'widgets-files-toggle',
'class' => 'sprite-conpher conpher_files_off first-icon'
),
''
),
javelin_tag(
'a',
array(
'sigil' => 'conpherence-change-widget',
'meta' => array(
'widget' => 'widgets-tasks',
'toggleClass' => 'conpher_list_on'
),
'id' => 'widgets-tasks-toggle',
'class' => 'sprite-conpher conpher_list_off conpher_list_on',
),
''
),
javelin_tag(
'a',
array(
'sigil' => 'conpherence-change-widget',
'meta' => array(
'widget' => 'widgets-calendar',
'toggleClass' => 'conpher_calendar_on'
),
'id' => 'widgets-calendar-toggle',
'class' => 'sprite-conpher conpher_calendar_off',
),
''
)
)
).
phutil_tag(
'div',
array(
'class' => 'widgets-body',
'id' => 'widgets-files',
'style' => 'display: none;'
),
$this->renderFilesWidgetPaneContent()
).
phutil_tag(
'div',
array(
'class' => 'widgets-body',
'id' => 'widgets-tasks',
),
$this->renderTaskWidgetPaneContent()
).
phutil_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 new PhutilSafeHTML($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 new PhutilSafeHTML(implode('', $content));
}
private function renderCalendarWidgetPaneContent() {
$user = $this->getRequest()->getUser();
$conpherence = $this->getConpherence();
$widget_data = $conpherence->getWidgetData();
$statuses = $widget_data['statuses'];
$handles = $conpherence->getHandles();
$content = array();
$timestamps = $this->getCalendarWidgetWeekTimestamps();
$one_day = 24 * 60 * 60;
foreach ($timestamps as $time => $day) {
// build a header for the new day
$content[] = id(new PhabricatorHeaderView())
->setHeader($day->format('l'))
->render();
$day->setTime(0, 0, 0);
$epoch_start = $day->format('U');
$day->modify('+1 day');
$epoch_end = $day->format('U');
// keep looking through statuses where we last left off
foreach ($statuses as $status) {
if ($status->getDateFrom() >= $epoch_end) {
// This list is sorted, so we can stop looking.
break;
}
if ($status->getDateFrom() < $epoch_end &&
$status->getDateTo() > $epoch_start) {
$timespan = $status->getDateTo() - $status->getDateFrom();
if ($timespan > $one_day) {
$time_str = 'm/d';
} else {
$time_str = 'h:i A';
}
$epoch_range = phabricator_format_local_time(
$status->getDateFrom(),
$user,
$time_str
) . ' - ' . phabricator_format_local_time(
$status->getDateTo(),
$user,
$time_str
);
$content[] = phutil_tag(
'div',
array(
'class' => 'user-status '.$status->getTextStatus(),
),
array(
phutil_tag(
'div',
array(
'class' => 'epoch-range'
),
$epoch_range
),
phutil_tag(
'div',
array(
'class' => 'icon',
),
''
),
phutil_tag(
'div',
array(
'class' => 'description'
),
$status->getTerseSummary($user)
),
phutil_tag(
'div',
array(
'class' => 'participant'
),
$handles[$status->getUserPHID()]->getName()
)
)
);
}
}
}
return new PhutilSafeHTML(implode('', $content));
}
private function getCalendarWidgetWeekTimestamps() {
$user = $this->getRequest()->getUser();
$timezone = new DateTimeZone($user->getTimezoneIdentifier());
$timestamps = array();
for ($day = 0; $day < 7; $day++) {
$timestamps[] = new DateTime(
sprintf('today +%d days', $day),
$timezone
);
}
return $timestamps;
}
}
diff --git a/src/applications/conpherence/editor/ConpherenceEditor.php b/src/applications/conpherence/editor/ConpherenceEditor.php
index a5b42b93ce..feabfd810b 100644
--- a/src/applications/conpherence/editor/ConpherenceEditor.php
+++ b/src/applications/conpherence/editor/ConpherenceEditor.php
@@ -1,238 +1,251 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
public function generateTransactionsFromText(
ConpherenceThread $conpherence,
$text) {
$files = array();
$file_phids =
PhabricatorMarkupEngine::extractFilePHIDsFromEmbeddedFiles(
array($text)
);
// Since these are extracted from text, we might be re-including the
// same file -- e.g. a mock under discussion. Filter files we
// already have.
$existing_file_phids = $conpherence->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_PICTURE_CROP;
$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();
+ return $object->getImagePHID(ConpherenceImageData::SIZE_ORIG);
+ case ConpherenceTransactionType::TYPE_PICTURE_CROP:
+ return $object->getImagePHID(ConpherenceImageData::SIZE_HEAD);
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:
+ case ConpherenceTransactionType::TYPE_PICTURE_CROP:
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());
+ $object->setImagePHID(
+ $xaction->getNewValue(),
+ ConpherenceImageData::SIZE_ORIG
+ );
+ break;
+ case ConpherenceTransactionType::TYPE_PICTURE_CROP:
+ $object->setImagePHID(
+ $xaction->getNewValue(),
+ ConpherenceImageData::SIZE_HEAD
+ );
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/conpherence/events/ConpherencePeopleMenuEventListener.php b/src/applications/conpherence/events/ConpherencePeopleMenuEventListener.php
new file mode 100644
index 0000000000..813763f9ae
--- /dev/null
+++ b/src/applications/conpherence/events/ConpherencePeopleMenuEventListener.php
@@ -0,0 +1,38 @@
+<?php
+
+final class ConpherencePeopleMenuEventListener extends PhutilEventListener {
+
+ public function register() {
+ $this->listen(PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU);
+ }
+
+ public function handleEvent(PhutilEvent $event) {
+ switch ($event->getType()) {
+ case PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU:
+ $this->handleMenuEvent($event);
+ break;
+ }
+ }
+
+ private function handleMenuEvent($event) {
+ $viewer = $event->getUser();
+ $menu = $event->getValue('menu');
+ $person = $event->getValue('person');
+
+ $conpherence_uri =
+ new PhutilURI('/conpherence/new/?participant='.$person->getPHID());
+ $name = pht('Conpherence');
+
+ $menu->addMenuItemBefore('activity',
+ id(new PhabricatorMenuItemView())
+ ->setIsExternal(true)
+ ->setName($name)
+ ->setHref($conpherence_uri)
+ ->setKey($name)
+ );
+
+ $event->setValue('menu', $menu);
+ }
+
+}
+
diff --git a/src/applications/conpherence/query/ConpherenceThreadQuery.php b/src/applications/conpherence/query/ConpherenceThreadQuery.php
index d22fd03820..e21951cf09 100644
--- a/src/applications/conpherence/query/ConpherenceThreadQuery.php
+++ b/src/applications/conpherence/query/ConpherenceThreadQuery.php
@@ -1,190 +1,243 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceThreadQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $phids;
private $ids;
private $needWidgetData;
+ private $needHeaderPics;
+ private $needOrigPics;
+
+ public function needOrigPics($need_orig_pics) {
+ $this->needOrigPics = $need_orig_pics;
+ return $this;
+ }
+
+ public function needHeaderPics($need_header_pics) {
+ $this->needHeaderPics = $need_header_pics;
+ return $this;
+ }
public function needWidgetData($need_widget_data) {
$this->needWidgetData = $need_widget_data;
return $this;
}
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function loadPage() {
$table = new ConpherenceThread();
$conn_r = $table->establishConnection('r');
$data = queryfx_all(
$conn_r,
'SELECT conpherence_thread.* FROM %T conpherence_thread %Q %Q %Q',
$table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$conpherences = $table->loadAllFromArray($data);
if ($conpherences) {
$conpherences = mpull($conpherences, null, 'getPHID');
$this->loadParticipants($conpherences);
$this->loadTransactionsAndHandles($conpherences);
$this->loadFilePHIDs($conpherences);
if ($this->needWidgetData) {
$this->loadWidgetData($conpherences);
}
+ if ($this->needOrigPics) {
+ $this->loadOrigPics($conpherences);
+ }
+ if ($this->needHeaderPics) {
+ $this->loadHeaderPics($conpherences);
+ }
}
return $conpherences;
}
protected function buildWhereClause($conn_r) {
$where = array();
$where[] = $this->buildPagingClause($conn_r);
if ($this->ids) {
$where[] = qsprintf(
$conn_r,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids) {
$where[] = qsprintf(
$conn_r,
'phid IN (%Ls)',
$this->phids);
}
return $this->formatWhereClause($where);
}
private function loadParticipants(array $conpherences) {
$participants = id(new ConpherenceParticipant())
->loadAllWhere('conpherencePHID IN (%Ls)', array_keys($conpherences));
$map = mgroup($participants, 'getConpherencePHID');
foreach ($map as $conpherence_phid => $conpherence_participants) {
$current_conpherence = $conpherences[$conpherence_phid];
$conpherence_participants = mpull(
$conpherence_participants,
null,
'getParticipantPHID'
);
$current_conpherence->attachParticipants($conpherence_participants);
}
return $this;
}
private function loadTransactionsAndHandles(array $conpherences) {
$transactions = id(new ConpherenceTransactionQuery())
->setViewer($this->getViewer())
->withObjectPHIDs(array_keys($conpherences))
->needHandles(true)
->loadPage();
$transactions = mgroup($transactions, 'getObjectPHID');
foreach ($conpherences as $phid => $conpherence) {
$current_transactions = $transactions[$phid];
$handles = array();
foreach ($current_transactions as $transaction) {
$handles += $transaction->getHandles();
}
$conpherence->attachHandles($handles);
$conpherence->attachTransactions($transactions[$phid]);
}
return $this;
}
private function loadFilePHIDs(array $conpherences) {
$edge_type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_FILE;
$file_edges = id(new PhabricatorEdgeQuery())
->withSourcePHIDs(array_keys($conpherences))
->withEdgeTypes(array($edge_type))
->execute();
foreach ($file_edges as $conpherence_phid => $data) {
$conpherence = $conpherences[$conpherence_phid];
$conpherence->attachFilePHIDs(array_keys($data[$edge_type]));
}
return $this;
}
private function loadWidgetData(array $conpherences) {
$participant_phids = array();
$file_phids = array();
foreach ($conpherences as $conpherence) {
$participant_phids[] = array_keys($conpherence->getParticipants());
$file_phids[] = $conpherence->getFilePHIDs();
}
$participant_phids = array_mergev($participant_phids);
$file_phids = array_mergev($file_phids);
// open tasks of all participants
$tasks = id(new ManiphestTaskQuery())
->withOwners($participant_phids)
->withStatus(ManiphestTaskQuery::STATUS_OPEN)
->execute();
$tasks = mgroup($tasks, 'getOwnerPHID');
// statuses of everyone currently in the conpherence
// for a rolling one week window
$start_of_week = phabricator_format_local_time(
strtotime('today'),
$this->getViewer(),
'U'
);
$end_of_week = phabricator_format_local_time(
strtotime('midnight +1 week'),
$this->getViewer(),
'U'
);
$statuses = id(new PhabricatorUserStatus())
->loadAllWhere(
'userPHID in (%Ls) AND dateTo >= %d AND dateFrom <= %d',
$participant_phids,
$start_of_week,
$end_of_week
);
$statuses = mgroup($statuses, 'getUserPHID');
// attached files
$files = array();
if ($file_phids) {
$files = id(new PhabricatorFileQuery())
->setViewer($this->getViewer())
->withPHIDs($file_phids)
->execute();
$files = mpull($files, null, 'getPHID');
}
foreach ($conpherences as $phid => $conpherence) {
$participant_phids = array_keys($conpherence->getParticipants());
$statuses = array_select_keys($statuses, $participant_phids);
$statuses = array_mergev($statuses);
$statuses = msort($statuses, 'getDateFrom');
$widget_data = array(
'tasks' => array_select_keys($tasks, $participant_phids),
'statuses' => $statuses,
'files' => array_select_keys($files, $conpherence->getFilePHIDs()),
);
$conpherence->attachWidgetData($widget_data);
}
return $this;
}
+ private function loadOrigPics(array $conpherences) {
+ return $this->loadPics(
+ $conpherences,
+ ConpherenceImageData::SIZE_ORIG
+ );
+ }
+
+ private function loadHeaderPics(array $conpherences) {
+ return $this->loadPics(
+ $conpherences,
+ ConpherenceImageData::SIZE_HEAD
+ );
+ }
+
+ private function loadPics(array $conpherences, $size) {
+ $conpherence_pic_phids = array();
+ foreach ($conpherences as $conpherence) {
+ $phid = $conpherence->getImagePHID($size);
+ if ($phid) {
+ $conpherence_pic_phids[$conpherence->getPHID()] = $phid;
+ }
+ }
+ $files = id(new PhabricatorFileQuery())
+ ->setViewer($this->getViewer())
+ ->withPHIDs($conpherence_pic_phids)
+ ->execute();
+ $files = mpull($files, null, 'getPHID');
+
+ foreach ($conpherence_pic_phids as $conpherence_phid => $pic_phid) {
+ $conpherences[$conpherence_phid]->setImage($files[$pic_phid], $size);
+ }
+
+ return $this;
+ }
+
}
diff --git a/src/applications/conpherence/storage/ConpherenceThread.php b/src/applications/conpherence/storage/ConpherenceThread.php
index 1b80aec1a5..e824ad6207 100644
--- a/src/applications/conpherence/storage/ConpherenceThread.php
+++ b/src/applications/conpherence/storage/ConpherenceThread.php
@@ -1,240 +1,300 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceThread extends ConpherenceDAO
implements PhabricatorPolicyInterface {
protected $id;
protected $phid;
protected $title;
- protected $imagePHID;
+ protected $imagePHIDs = array();
protected $mailKey;
private $participants;
private $transactions;
private $handles;
private $filePHIDs;
private $widgetData;
+ private $images = array();
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
+ self::CONFIG_SERIALIZATION => array(
+ 'imagePHIDs' => self::SERIALIZATION_JSON,
+ ),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorPHIDConstants::PHID_TYPE_CONP);
}
public function save() {
if (!$this->getMailKey()) {
$this->setMailKey(Filesystem::readRandomCharacters(20));
}
return parent::save();
}
+ public function getImagePHID($size) {
+ $image_phids = $this->getImagePHIDs();
+ return idx($image_phids, $size);
+ }
+ public function setImagePHID($phid, $size) {
+ $image_phids = $this->getImagePHIDs();
+ $image_phids[$size] = $phid;
+ return $this->setImagePHIDs($image_phids);
+ }
+
+ public function getImage($size) {
+ $images = $this->getImages();
+ return idx($images, $size);
+ }
+ public function setImage(PhabricatorFile $file, $size) {
+ $files = $this->getImages();
+ $files[$size] = $file;
+ return $this->setImages($files);
+ }
+ public function setImages(array $files) {
+ $this->images = $files;
+ return $this;
+ }
+ private function getImages() {
+ return $this->images;
+ }
+
public function attachParticipants(array $participants) {
assert_instances_of($participants, 'ConpherenceParticipant');
$this->participants = $participants;
return $this;
}
public function getParticipants() {
if ($this->participants === null) {
throw new Exception(
'You must attachParticipants first!'
);
}
return $this->participants;
}
public function getParticipant($phid) {
$participants = $this->getParticipants();
return $participants[$phid];
}
public function getParticipantPHIDs() {
$participants = $this->getParticipants();
return array_keys($participants);
}
public function attachHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
public function getHandles() {
if ($this->handles === null) {
throw new Exception(
'You must attachHandles first!'
);
}
return $this->handles;
}
public function attachTransactions(array $transactions) {
assert_instances_of($transactions, 'ConpherenceTransaction');
$this->transactions = $transactions;
return $this;
}
public function getTransactions() {
if ($this->transactions === null) {
throw new Exception(
'You must attachTransactions first!'
);
}
return $this->transactions;
}
public function attachFilePHIDs(array $file_phids) {
$this->filePHIDs = $file_phids;
return $this;
}
public function getFilePHIDs() {
if ($this->filePHIDs === null) {
throw new Exception(
'You must attachFilePHIDs first!'
);
}
return $this->filePHIDs;
}
public function attachWidgetData(array $widget_data) {
$this->widgetData = $widget_data;
return $this;
}
public function getWidgetData() {
if ($this->widgetData === null) {
throw new Exception(
'You must attachWidgetData first!'
);
}
return $this->widgetData;
}
- public function loadImageURI() {
- $src_phid = $this->getImagePHID();
+ public function loadImageURI($size) {
+ $file = $this->getImage($size);
- if ($src_phid) {
- $file = id(new PhabricatorFile())->loadOneWhere('phid = %s', $src_phid);
- if ($file) {
- return $file->getBestURI();
- }
+ if ($file) {
+ return $file->getBestURI();
}
return PhabricatorUser::getDefaultProfileImageURI();
}
- public function getDisplayData(PhabricatorUser $user) {
+ public function getDisplayData(PhabricatorUser $user, $size) {
$transactions = $this->getTransactions();
- $latest_transaction = end($transactions);
- $latest_participant = $latest_transaction->getAuthorPHID();
- $handles = $this->getHandles();
- $latest_handle = $handles[$latest_participant];
- if ($this->getImagePHID()) {
- $img_src = $this->loadImageURI();
- } else {
- $img_src = $latest_handle->getImageURI();
- }
- $title = $this->getTitle();
- if (!$title) {
- $title = $latest_handle->getName();
- unset($handles[$latest_participant]);
- }
- unset($handles[$user->getPHID()]);
- $subtitle = '';
- $count = 0;
- $final = false;
- foreach ($handles as $handle) {
- if ($handle->getType() != PhabricatorPHIDConstants::PHID_TYPE_USER) {
- continue;
- }
- if ($subtitle) {
- if ($final) {
- $subtitle .= '...';
- break;
- } else {
- $subtitle .= ', ';
- }
- }
- $subtitle .= $handle->getName();
- $count++;
- $final = $count == 3;
+ $handles = $this->getHandles();
+ // we don't want to show the user unless they are babbling to themselves
+ if (count($handles) > 1) {
+ unset($handles[$user->getPHID()]);
}
$participants = $this->getParticipants();
$user_participation = $participants[$user->getPHID()];
+ $latest_transaction = null;
+ $title = $this->getTitle();
+ $subtitle = '';
+ $img_src = null;
+ $img_class = null;
+ if ($this->getImagePHID($size)) {
+ $img_src = $this->getImage($size)->getBestURI();
+ $img_class = 'custom-';
+ }
$unread_count = 0;
$max_count = 10;
$snippet = null;
if (!$user_participation->isUpToDate()) {
$behind_transaction_phid =
$user_participation->getBehindTransactionPHID();
} else {
$behind_transaction_phid = null;
}
foreach (array_reverse($transactions) as $transaction) {
switch ($transaction->getTransactionType()) {
case ConpherenceTransactionType::TYPE_PARTICIPANTS:
case ConpherenceTransactionType::TYPE_TITLE:
case ConpherenceTransactionType::TYPE_PICTURE:
continue 2;
case PhabricatorTransactions::TYPE_COMMENT:
if ($snippet === null) {
$snippet = phutil_utf8_shorten(
$transaction->getComment()->getContent(),
48
);
+ if ($transaction->getAuthorPHID() == $user->getPHID()) {
+ $snippet = "\xE2\x86\xB0 " . $snippet;
+ }
}
// fallthrough intentionally here
case ConpherenceTransactionType::TYPE_FILES:
+ if (!$latest_transaction) {
+ $latest_transaction = $transaction;
+ }
+ $latest_participant_phid = $transaction->getAuthorPHID();
+ if ((!$title || !$img_src) &&
+ $latest_participant_phid != $user->getPHID()) {
+ $latest_handle = $handles[$latest_participant_phid];
+ if (!$img_src) {
+ $img_src = $latest_handle->getImageURI();
+ }
+ if (!$title) {
+ $title = $latest_handle->getName();
+ // (maybs) used the pic, definitely used the name -- discard
+ unset($handles[$latest_participant_phid]);
+ }
+ }
if ($behind_transaction_phid) {
$unread_count++;
if ($transaction->getPHID() == $behind_transaction_phid) {
break 2;
}
}
if ($unread_count > $max_count) {
break 2;
}
break;
default:
continue 2;
}
if ($snippet && !$behind_transaction_phid) {
break;
}
}
if ($unread_count > $max_count) {
$unread_count = $max_count.'+';
}
+ // This happens if the user has been babbling, maybs just to themselves,
+ // but enough un-responded to transactions for our SQL limit would
+ // hit this too... Also happens on new threads since only the first
+ // author has participated.
+ // ...so just pick a different handle in these cases.
+ $some_handle = reset($handles);
+ if (!$img_src) {
+ $img_src = $some_handle->getImageURI();
+ }
+ if (!$title) {
+ $title = $some_handle->getName();
+ }
+
+ $count = 0;
+ $final = false;
+ foreach ($handles as $handle) {
+ if ($handle->getType() != PhabricatorPHIDConstants::PHID_TYPE_USER) {
+ continue;
+ }
+ if ($subtitle) {
+ if ($final) {
+ $subtitle .= '...';
+ break;
+ } else {
+ $subtitle .= ', ';
+ }
+ }
+ $subtitle .= $handle->getName();
+ $count++;
+ $final = $count == 3;
+ }
+
return array(
'title' => $title,
'subtitle' => $subtitle,
'unread_count' => $unread_count,
'epoch' => $latest_transaction->getDateCreated(),
'image' => $img_src,
+ 'image_class' => $img_class,
'snippet' => $snippet,
);
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
return PhabricatorPolicies::POLICY_NOONE;
}
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
$participants = $this->getParticipants();
return isset($participants[$user->getPHID()]);
}
}
diff --git a/src/applications/conpherence/storage/ConpherenceTransaction.php b/src/applications/conpherence/storage/ConpherenceTransaction.php
index 9b242275c6..22a4aa666e 100644
--- a/src/applications/conpherence/storage/ConpherenceTransaction.php
+++ b/src/applications/conpherence/storage/ConpherenceTransaction.php
@@ -1,125 +1,124 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceTransaction extends PhabricatorApplicationTransaction {
public function getApplicationName() {
return 'conpherence';
}
public function getApplicationTransactionType() {
return PhabricatorPHIDConstants::PHID_TYPE_CONP;
}
public function getApplicationTransactionCommentObject() {
return new ConpherenceTransactionComment();
}
public function getApplicationObjectTypeName() {
return pht('conpherence');
}
public function shouldHide() {
$old = $this->getOldValue();
switch ($this->getTransactionType()) {
case ConpherenceTransactionType::TYPE_PARTICIPANTS:
return ($old === null);
case ConpherenceTransactionType::TYPE_TITLE:
case ConpherenceTransactionType::TYPE_PICTURE:
return false;
case ConpherenceTransactionType::TYPE_FILES:
+ case ConpherenceTransactionType::TYPE_PICTURE_CROP:
return true;
}
return parent::shouldHide();
}
public function getTitle() {
$author_phid = $this->getAuthorPHID();
$old = $this->getOldValue();
$new = $this->getNewValue();
switch ($this->getTransactionType()) {
case ConpherenceTransactionType::TYPE_TITLE:
if ($old) {
$title = pht(
'%s renamed this conpherence from "%s" to "%s".',
$this->renderHandleLink($author_phid),
phutil_escape_html($old),
phutil_escape_html($new));
} else {
$title = pht(
'%s named this conpherence "%s".',
$this->renderHandleLink($author_phid),
phutil_escape_html($new));
}
return $title;
case ConpherenceTransactionType::TYPE_FILES:
return pht(
'%s updated the conpherence files.',
$this->renderHandleLink($author_phid));
case ConpherenceTransactionType::TYPE_PICTURE:
return pht(
'%s updated the conpherence image.',
$this->renderHandleLink($author_phid));
case ConpherenceTransactionType::TYPE_PARTICIPANTS:
$add = array_diff($new, $old);
$rem = array_diff($old, $new);
if ($add && $rem) {
$title = pht(
'%s edited participant(s), added %d: %s; removed %d: %s.',
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add),
count($rem),
$this->renderHandleList($rem));
} else if ($add) {
$title = pht(
'%s added %d participant(s): %s.',
$this->renderHandleLink($author_phid),
count($add),
$this->renderHandleList($add));
} else {
$title = pht(
'%s removed %d partipant(s): %s.',
$this->renderHandleLink($author_phid),
count($rem),
$this->renderHandleList($rem));
}
return $title;
break;
}
return parent::getTitle();
}
public function getRequiredHandlePHIDs() {
$phids = parent::getRequiredHandlePHIDs();
$old = $this->getOldValue();
$new = $this->getNewValue();
$phids[] = $this->getAuthorPHID();
switch ($this->getTransactionType()) {
case ConpherenceTransactionType::TYPE_PICTURE:
- $phids[] = $new;
- break;
case ConpherenceTransactionType::TYPE_TITLE:
+ case ConpherenceTransactionType::TYPE_FILES:
break;
case ConpherenceTransactionType::TYPE_PARTICIPANTS:
- case ConpherenceTransactionType::TYPE_FILES:
$phids = array_merge($phids, $this->getOldValue());
$phids = array_merge($phids, $this->getNewValue());
break;
}
return $phids;
}
}
diff --git a/src/applications/conpherence/view/ConpherenceFormDragAndDropUploadControl.php b/src/applications/conpherence/view/ConpherenceFormDragAndDropUploadControl.php
new file mode 100644
index 0000000000..032d8a9aa7
--- /dev/null
+++ b/src/applications/conpherence/view/ConpherenceFormDragAndDropUploadControl.php
@@ -0,0 +1,42 @@
+<?php
+
+final class ConpherenceFormDragAndDropUploadControl extends AphrontFormControl {
+
+ private $dropID;
+
+ public function setDropID($drop_id) {
+ $this->dropID = $drop_id;
+ return $this;
+ }
+ public function getDropID() {
+ return $this->dropID;
+ }
+
+ protected function getCustomControlClass() {
+ return null;
+ }
+
+ protected function renderInput() {
+
+ $drop_id = celerity_generate_unique_node_id();
+ Javelin::initBehavior('conpherence-drag-and-drop-photo',
+ array(
+ 'target' => $drop_id,
+ 'form_pane' => 'conpherence-form',
+ 'upload_uri' => '/file/dropupload/',
+ 'activated_class' => 'conpherence-dialogue-upload-photo',
+ )
+ );
+ require_celerity_resource('conpherence-update-css');
+
+ return phutil_tag(
+ 'div',
+ array(
+ 'id' => $drop_id,
+ 'class' => 'conpherence-dialogue-drag-photo',
+ ),
+ pht('Drag and drop an image here to upload it.')
+ );
+ }
+
+}
diff --git a/src/applications/conpherence/view/ConpherenceTransactionView.php b/src/applications/conpherence/view/ConpherenceTransactionView.php
index 7e6c842526..5c8c8a9ba1 100644
--- a/src/applications/conpherence/view/ConpherenceTransactionView.php
+++ b/src/applications/conpherence/view/ConpherenceTransactionView.php
@@ -1,98 +1,99 @@
<?php
/**
* @group conpherence
*/
final class ConpherenceTransactionView extends AphrontView {
private $conpherenceTransaction;
private $handles;
+ private $markupEngine;
+
+ public function setMarkupEngine(PhabricatorMarkupEngine $markup_engine) {
+ $this->markupEngine = $markup_engine;
+ return $this;
+ }
public function setHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
public function getHandles() {
return $this->handles;
}
public function setConpherenceTransaction(ConpherenceTransaction $tx) {
$this->conpherenceTransaction = $tx;
return $this;
}
private function getConpherenceTransaction() {
return $this->conpherenceTransaction;
}
public function render() {
$transaction = $this->getConpherenceTransaction();
$handles = $this->getHandles();
$transaction->setHandles($handles);
$author = $handles[$transaction->getAuthorPHID()];
$transaction_view = id(new PhabricatorTransactionView())
->setUser($this->getUser())
->setEpoch($transaction->getDateCreated())
->setContentSource($transaction->getContentSource());
$content = null;
$content_class = null;
+ $content = null;
switch ($transaction->getTransactionType()) {
case ConpherenceTransactionType::TYPE_TITLE:
+ case ConpherenceTransactionType::TYPE_PICTURE:
+ case ConpherenceTransactionType::TYPE_PICTURE_CROP:
$content = $transaction->getTitle();
$transaction_view->addClass('conpherence-edited');
break;
case ConpherenceTransactionType::TYPE_FILES:
$content = $transaction->getTitle();
break;
case ConpherenceTransactionType::TYPE_PICTURE:
$img = $transaction->getHandle($transaction->getNewValue());
- $content = $transaction->getTitle() .
+ $content = array(
+ $transaction->getTitle(),
phutil_tag(
'img',
array(
'src' => $img->getImageURI()
- ));
+ )));
$transaction_view->addClass('conpherence-edited');
break;
case ConpherenceTransactionType::TYPE_PARTICIPANTS:
$content = $transaction->getTitle();
$transaction_view->addClass('conpherence-edited');
break;
case PhabricatorTransactions::TYPE_COMMENT:
$comment = $transaction->getComment();
$file_ids =
PhabricatorMarkupEngine::extractFilePHIDsFromEmbeddedFiles(
array($comment->getContent())
);
- $markup_field = ConpherenceTransactionComment::MARKUP_FIELD_COMMENT;
- $engine = id(new PhabricatorMarkupEngine())
- ->setViewer($this->getUser());
- $engine->addObject(
- $comment,
- $markup_field
- );
- $engine->process();
- $content = $engine->getOutput(
+ $content = $this->markupEngine->getOutput(
$comment,
- $markup_field
- );
+ PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT);
$content_class = 'conpherence-message phabricator-remarkup';
$transaction_view
->setImageURI($author->getImageURI())
->setActions(array($author->renderLink()));
break;
}
$transaction_view
->appendChild(phutil_tag(
'div',
array(
'class' => $content_class
),
- new PhutilSafeHTML($content))
+ $this->renderHTMLView($content))
);
return $transaction_view->render();
}
}
diff --git a/src/applications/differential/application/PhabricatorApplicationDifferential.php b/src/applications/differential/application/PhabricatorApplicationDifferential.php
index baa795589a..a198b98d59 100644
--- a/src/applications/differential/application/PhabricatorApplicationDifferential.php
+++ b/src/applications/differential/application/PhabricatorApplicationDifferential.php
@@ -1,104 +1,110 @@
<?php
final class PhabricatorApplicationDifferential extends PhabricatorApplication {
public function getBaseURI() {
return '/differential/';
}
public function getShortDescription() {
return pht('Review Code');
}
public function getIconName() {
return 'differential';
}
public function getHelpURI() {
return PhabricatorEnv::getDoclink('article/Differential_User_Guide.html');
}
public function getFactObjectsForAnalysis() {
return array(
new DifferentialRevision(),
);
}
public function getTitleGlyph() {
return "\xE2\x9A\x99";
}
+ public function getEventListeners() {
+ return array(
+ new DifferentialPeopleMenuEventListener()
+ );
+ }
+
public function getRoutes() {
return array(
'/D(?P<id>[1-9]\d*)' => 'DifferentialRevisionViewController',
'/differential/' => array(
'' => 'DifferentialRevisionListController',
'filter/(?P<filter>\w+)/(?:(?P<username>[\w\.-_]+)/)?' =>
'DifferentialRevisionListController',
'stats/(?P<filter>\w+)/' => 'DifferentialRevisionStatsController',
'diff/' => array(
'(?P<id>[1-9]\d*)/' => 'DifferentialDiffViewController',
'create/' => 'DifferentialDiffCreateController',
),
'changeset/' => 'DifferentialChangesetViewController',
'revision/edit/(?:(?P<id>[1-9]\d*)/)?'
=> 'DifferentialRevisionEditController',
'comment/' => array(
'preview/(?P<id>[1-9]\d*)/' => 'DifferentialCommentPreviewController',
'save/' => 'DifferentialCommentSaveController',
'inline/' => array(
'preview/(?P<id>[1-9]\d*)/'
=> 'DifferentialInlineCommentPreviewController',
'edit/(?P<id>[1-9]\d*)/'
=> 'DifferentialInlineCommentEditController',
),
),
'subscribe/(?P<action>add|rem)/(?P<id>[1-9]\d*)/'
=> 'DifferentialSubscribeController',
),
);
}
public function getApplicationGroup() {
return self::GROUP_CORE;
}
public function getApplicationOrder() {
return 0.100;
}
public function loadStatus(PhabricatorUser $user) {
$revisions = id(new DifferentialRevisionQuery())
->withResponsibleUsers(array($user->getPHID()))
->withStatus(DifferentialRevisionQuery::STATUS_OPEN)
->execute();
list($blocking, $active, $waiting) =
DifferentialRevisionQuery::splitResponsible(
$revisions,
array($user->getPHID()));
$status = array();
$active = count($blocking) + count($active);
$type = $active
? PhabricatorApplicationStatusView::TYPE_NEEDS_ATTENTION
: PhabricatorApplicationStatusView::TYPE_EMPTY;
$status[] = id(new PhabricatorApplicationStatusView())
->setType($type)
->setText(pht('%d Review(s) Need Attention', $active))
->setCount($active);
$waiting = count($waiting);
$type = $waiting
? PhabricatorApplicationStatusView::TYPE_INFO
: PhabricatorApplicationStatusView::TYPE_EMPTY;
$status[] = id(new PhabricatorApplicationStatusView())
->setType($type)
->setText(pht('%d Review(s) Waiting on Others', $waiting));
return $status;
}
}
diff --git a/src/applications/differential/conduit/ConduitAPI_differential_getdiff_Method.php b/src/applications/differential/conduit/ConduitAPI_differential_getdiff_Method.php
index 5f2719691d..55872bec32 100644
--- a/src/applications/differential/conduit/ConduitAPI_differential_getdiff_Method.php
+++ b/src/applications/differential/conduit/ConduitAPI_differential_getdiff_Method.php
@@ -1,80 +1,79 @@
<?php
/**
* @group conduit
*/
final class ConduitAPI_differential_getdiff_Method extends ConduitAPIMethod {
public function getMethodDescription() {
return "Load the content of a diff from Differential.";
}
public function defineParamTypes() {
return array(
'revision_id' => 'optional id',
'diff_id' => 'optional id',
);
}
public function defineReturnType() {
return 'nonempty dict';
}
public function defineErrorTypes() {
return array(
'ERR_BAD_REVISION' => 'No such revision exists.',
'ERR_BAD_DIFF' => 'No such diff exists.',
);
}
public function shouldRequireAuthentication() {
return !PhabricatorEnv::getEnvConfig('differential.anonymous-access');
}
protected function execute(ConduitAPIRequest $request) {
$diff = null;
$revision_id = $request->getValue('revision_id');
if ($revision_id) {
$revision = id(new DifferentialRevision())->load($revision_id);
if (!$revision) {
throw new ConduitException('ERR_BAD_REVISION');
}
$diff = id(new DifferentialDiff())->loadOneWhere(
'revisionID = %d ORDER BY id DESC LIMIT 1',
$revision->getID());
} else {
$diff_id = $request->getValue('diff_id');
if ($diff_id) {
$diff = id(new DifferentialDiff())->load($diff_id);
}
}
if (!$diff) {
throw new ConduitException('ERR_BAD_DIFF');
}
$diff->attachChangesets(
$diff->loadRelatives(new DifferentialChangeset(), 'diffID'));
foreach ($diff->getChangesets() as $changeset) {
$changeset->attachHunks(
$changeset->loadRelatives(new DifferentialHunk(), 'changesetID'));
}
$basic_dict = $diff->getDiffDict();
// for conduit calls, the basic dict is not enough
// we also need to include the arcanist project and author information
$project = $diff->loadArcanistProject();
if ($project) {
$project_name = $project->getName();
} else {
$project_name = null;
}
$basic_dict['projectName'] = $project_name;
- $basic_dict['author'] = $diff->loadAuthorInformation();
return $basic_dict;
}
}
diff --git a/src/applications/differential/config/PhabricatorDifferentialConfigOptions.php b/src/applications/differential/config/PhabricatorDifferentialConfigOptions.php
index 9f077e1c85..f16bfbfc98 100644
--- a/src/applications/differential/config/PhabricatorDifferentialConfigOptions.php
+++ b/src/applications/differential/config/PhabricatorDifferentialConfigOptions.php
@@ -1,289 +1,267 @@
<?php
final class PhabricatorDifferentialConfigOptions
extends PhabricatorApplicationConfigOptions {
public function getName() {
return pht('Differential');
}
public function getDescription() {
return pht('Configure Differential code review.');
}
public function getOptions() {
return array(
$this->newOption(
'differential.revision-custom-detail-renderer',
'class',
null)
->setBaseClass('DifferentialRevisionDetailRenderer')
->setDescription(pht("Custom revision detail renderer.")),
$this->newOption(
'differential.custom-remarkup-rules',
'list<string>',
array())
->setSummary(pht('Custom remarkup rules.'))
->setDescription(
pht(
"Array for custom remarkup rules. The array should have a list ".
"of class names of classes that extend PhutilRemarkupRule")),
$this->newOption(
'differential.custom-remarkup-block-rules',
'list<string>',
array())
->setSummary(pht('Custom remarkup block rules.'))
->setDescription(
pht(
"Array for custom remarkup block rules. The array should have a ".
"list of class names of classes that extend ".
"PhutilRemarkupEngineBlockRule")),
$this->newOption(
'differential.whitespace-matters',
'list<string>',
array(
'/\.py$/',
'/\.l?hs$/',
))
->setDescription(
pht(
"List of file regexps where whitespace is meaningful and should ".
"not use 'ignore-all' by default")),
$this->newOption(
'differential.field-selector',
'class',
'DifferentialDefaultFieldSelector')
->setBaseClass('DifferentialFieldSelector')
->setDescription(pht('Field selector class')),
$this->newOption('differential.show-host-field', 'bool', false)
->setBoolOptions(
array(
pht('Show "Host" Fields'),
pht('Hide "Host" Fields'),
))
->setSummary(pht('Show or hide the "Host" and "Path" fields.'))
->setDescription(
pht(
'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, but '.
'they can be useful if you work in an environment with shared '.
'development machines. You can set this option to true to enable '.
'these fields.')),
$this->newOption('differential.show-test-plan-field', 'bool', true)
->setBoolOptions(
array(
pht('Show "Test Plan" Field'),
pht('Hide "Test Plan" Field'),
))
->setSummary(pht('Show or hide the "Test Plan" field.'))
->setDescription(
pht(
'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 they send code for review. '.
'If you would prefer not to use this field, you can disable it '.
'here. You can also make it optional (instead of required) by '.
'setting {{differential.require-test-plan-field}}.')),
$this->newOption('differential.require-test-plan-field', 'bool', true)
->setBoolOptions(
array(
pht("Require 'Test Plan' field"),
pht("Make 'Test Plan' field optional"),
))
->setSummary(pht('Require "Test Plan" field?'))
->setDescription(
pht(
"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.")),
$this->newOption('differential.enable-email-accept', 'bool', false)
->setBoolOptions(
array(
pht('Enable Email "!accept" Action'),
pht('Disable Email "!accept" Action'),
))
->setSummary(pht('Enable or disable "!accept" action via email.'))
->setDescription(
pht(
'If inbound email is configured, users can interact with '.
'revisions by using "!actions" in email replies (for example, '.
'"!resign" or "!rethink"). However, by default, users may not '.
'"!accept" revisions via email: email authentication can be '.
'configured to be very weak, and email "!accept" is kind of '.
'sketchy and implies the revision may not actually be receiving '.
'thorough review. You can enable "!accept" by setting this '.
'option to true.')),
$this->newOption('differential.anonymous-access', 'bool', false)
->setBoolOptions(
array(
pht('Allow guests to view revisions'),
pht('Require authentication to view revisions'),
))
->setSummary(pht('Anonymous access to Differential revisions.'))
->setDescription(
pht(
"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.")),
- $this->newOption('differential.expose-emails-prudently', 'bool', false)
- ->setBoolOptions(
- array(
- pht("Expose revision author email address via Conduit"),
- pht("Don't expose revision author email address via Conduit"),
- ))
- ->setSummary(
- pht(
- "Determines whether or not the author's email address should be ".
- "exposed via Conduit."))
- ->setDescription(
- pht(
- "If you set this to true, revision author email address ".
- "information will be exposed in Conduit. This is useful for ".
- "Arcanist.\n\n".
- "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 ".
- "<gwashinton@example.com>' 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'.")),
$this->newOption('differential.generated-paths', 'list<string>', array())
->setSummary(pht("File regexps to treat as automatically generated."))
->setDescription(
pht(
"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."))
->addExample('["/config\.h$/", "#/autobuilt/#"]', pht("Valid Setting")),
$this->newOption('differential.allow-self-accept', 'bool', false)
->setBoolOptions(
array(
pht("Allow self-accept"),
pht("Disallow self-accept"),
))
->setSummary(pht("Allows users to accept their own revisions."))
->setDescription(
pht(
"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.")),
$this->newOption('differential.always-allow-close', 'bool', false)
->setBoolOptions(
array(
pht("Allow any user"),
pht("Restrict to submitter"),
))
->setSummary(pht("Allows any user to close accepted revisions."))
->setDescription(
pht(
"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.")),
$this->newOption('differential.allow-reopen', 'bool', false)
->setBoolOptions(
array(
pht("Enable reopen"),
pht("Disable reopen"),
))
->setSummary(pht("Allows any user to reopen a closed revision."))
->setDescription(
pht("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.")),
$this->newOption('differential.days-fresh', 'int', 1)
->setSummary(
pht(
"For how many business days should a revision be considered ".
"'fresh'?"))
->setDescription(
pht(
"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.")),
$this->newOption('differential.days-stale', 'int', 3)
->setSummary(
pht("After this many days, a revision will be considered 'stale'."))
->setDescription(
pht(
"Similar to `differential.days-fresh` but marks stale revisions. ".
"If the revision is even older than it is when marked as 'old'.")),
$this->newOption(
'metamta.differential.reply-handler-domain',
'string',
null)
->setDescription(
pht('Inbound email domain for Differential replies.')),
$this->newOption(
'metamta.differential.reply-handler',
'class',
'DifferentialReplyHandler')
->setBaseClass('PhabricatorMailReplyHandler')
->setDescription(pht('Alternate reply handler class.')),
$this->newOption(
'metamta.differential.subject-prefix',
'string',
'[Differential]')
->setDescription(pht('Subject prefix for Differential mail.')),
$this->newOption(
'metamta.differential.attach-patches',
'bool',
false)
->setBoolOptions(
array(
pht("Attach Patches"),
pht("Do Not Attach Patches"),
))
->setSummary(pht("Attach patches to email, as text attachments."))
->setDescription(
pht(
"If you set this to true, Phabricator will attach patches to ".
"Differential mail (as text attachments). This will not work if ".
"you are using SendGrid as your mail adapter.")),
$this->newOption(
'metamta.differential.inline-patches',
'int',
0)
->setSummary(pht("Inline patches in email, as body text."))
->setDescription(
pht(
"To include patches inline 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.")),
// TODO: Implement 'enum'? Options are 'unified' or 'git'.
$this->newOption(
'metamta.differential.patch-format',
'string',
'unified')
->setDescription(
pht("Format for inlined or attached patches: 'git' or 'unified'.")),
$this->newOption(
'metamta.differential.unified-comment-context',
'bool',
false)
->setBoolOptions(
array(
pht("Do not show context"),
pht("Show context"),
))
->setSummary(pht("Show diff context around inline comments in email."))
->setDescription(
pht(
"Normally, inline comments in emails are shown with a file and ".
"line but without any diff context. Enabling this option adds ".
"diff context.")),
);
}
}
diff --git a/src/applications/differential/events/DifferentialPeopleMenuEventListener.php b/src/applications/differential/events/DifferentialPeopleMenuEventListener.php
new file mode 100644
index 0000000000..59163ecdf3
--- /dev/null
+++ b/src/applications/differential/events/DifferentialPeopleMenuEventListener.php
@@ -0,0 +1,38 @@
+<?php
+
+final class DifferentialPeopleMenuEventListener extends PhutilEventListener {
+
+ public function register() {
+ $this->listen(PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU);
+ }
+
+ public function handleEvent(PhutilEvent $event) {
+ switch ($event->getType()) {
+ case PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU:
+ $this->handleMenuEvent($event);
+ break;
+ }
+ }
+
+ private function handleMenuEvent($event) {
+ $viewer = $event->getUser();
+ $menu = $event->getValue('menu');
+ $person = $event->getValue('person');
+ $username = phutil_escape_uri($person->getUserName());
+
+ $href = '/differential/filter/revisions/'.$username.'/';
+ $name = pht('Revisions');
+
+ $menu->addMenuItemToLabel('activity',
+ id(new PhabricatorMenuItemView())
+ ->setIsExternal(true)
+ ->setHref($href)
+ ->setName($name)
+ ->setKey($name)
+ );
+
+ $event->setValue('menu', $menu);
+ }
+
+}
+
diff --git a/src/applications/differential/storage/DifferentialDiff.php b/src/applications/differential/storage/DifferentialDiff.php
index 11e4a754b2..1acf8f5508 100644
--- a/src/applications/differential/storage/DifferentialDiff.php
+++ b/src/applications/differential/storage/DifferentialDiff.php
@@ -1,294 +1,256 @@
<?php
final class DifferentialDiff extends DifferentialDAO {
protected $revisionID;
protected $authorPHID;
protected $sourceMachine;
protected $sourcePath;
protected $sourceControlSystem;
protected $sourceControlBaseRevision;
protected $sourceControlPath;
protected $lintStatus;
protected $unitStatus;
protected $lineCount;
protected $branch;
protected $bookmark;
protected $parentRevisionID;
protected $arcanistProjectPHID;
protected $creationMethod;
protected $repositoryUUID;
protected $description;
private $unsavedChangesets = array();
private $changesets;
public function addUnsavedChangeset(DifferentialChangeset $changeset) {
if ($this->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 <gwashington@example.com>" 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);
+ if ($property->getName() == 'local:commits') {
+ foreach ($property->getData() as $commit) {
+ $dict['authorName'] = $commit['author'];
+ $dict['authorEmail'] = $commit['authorEmail'];
+ break;
}
- 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;
+ return $dict;
}
- private function getFullAuthorInfo(PhabricatorUser $author) {
- return sprintf('%s <%s>',
- $author->getRealName(),
- $author->loadPrimaryEmailAddress());
- }
}
diff --git a/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php b/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
index 7eb4f27ccd..588c179d15 100644
--- a/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
+++ b/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
@@ -1,80 +1,86 @@
<?php
final class PhabricatorApplicationDiffusion extends PhabricatorApplication {
public function getShortDescription() {
return 'Repository Browser';
}
public function getBaseURI() {
return '/diffusion/';
}
public function getIconName() {
return 'diffusion';
}
public function getHelpURI() {
return PhabricatorEnv::getDoclink('article/Diffusion_User_Guide.html');
}
public function getFactObjectsForAnalysis() {
return array(
new PhabricatorRepositoryCommit(),
);
}
+ public function getEventListeners() {
+ return array(
+ new DiffusionPeopleMenuEventListener()
+ );
+ }
+
public function getRoutes() {
return array(
'/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)'
=> 'DiffusionCommitController',
'/diffusion/' => array(
'' => 'DiffusionHomeController',
'(?P<callsign>[A-Z]+)/' => array(
'' => 'DiffusionRepositoryController',
'repository/(?P<dblob>.*)' => 'DiffusionRepositoryController',
'change/(?P<dblob>.*)' => 'DiffusionChangeController',
'history/(?P<dblob>.*)' => 'DiffusionHistoryController',
'browse/(?P<dblob>.*)' => 'DiffusionBrowseController',
'lastmodified/(?P<dblob>.*)' => 'DiffusionLastModifiedController',
'diff/' => 'DiffusionDiffController',
'tags/(?P<dblob>.*)' => 'DiffusionTagListController',
'branches/(?P<dblob>.*)' => 'DiffusionBranchTableController',
'lint/(?P<dblob>.*)' => 'DiffusionLintController',
'commit/(?P<commit>[a-z0-9]+)/branches/'
=> 'DiffusionCommitBranchesController',
'commit/(?P<commit>[a-z0-9]+)/tags/'
=> 'DiffusionCommitTagsController',
'commit/(?P<commit>[a-z0-9]+)/edit/'
=> 'DiffusionCommitEditController',
),
'inline/' => array(
'edit/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController',
'preview/(?P<phid>[^/]+)/' =>
'DiffusionInlineCommentPreviewController',
),
'services/' => array(
'path/' => array(
'complete/' => 'DiffusionPathCompleteController',
'validate/' => 'DiffusionPathValidateController',
),
),
'symbol/(?P<name>[^/]+)/' => 'DiffusionSymbolController',
'external/' => 'DiffusionExternalController',
'lint/' => 'DiffusionLintController',
),
);
}
public function getApplicationGroup() {
return self::GROUP_CORE;
}
public function getApplicationOrder() {
return 0.120;
}
}
diff --git a/src/applications/diffusion/events/DiffusionPeopleMenuEventListener.php b/src/applications/diffusion/events/DiffusionPeopleMenuEventListener.php
new file mode 100644
index 0000000000..fc7e5a670d
--- /dev/null
+++ b/src/applications/diffusion/events/DiffusionPeopleMenuEventListener.php
@@ -0,0 +1,37 @@
+<?php
+
+final class DiffusionPeopleMenuEventListener extends PhutilEventListener {
+
+ public function register() {
+ $this->listen(PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU);
+ }
+
+ public function handleEvent(PhutilEvent $event) {
+ switch ($event->getType()) {
+ case PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU:
+ $this->handleMenuEvent($event);
+ break;
+ }
+ }
+
+ private function handleMenuEvent($event) {
+ $viewer = $event->getUser();
+ $menu = $event->getValue('menu');
+ $person_phid = $event->getValue('person')->getPHID();
+
+ $href = '/diffusion/lint/?owner[0]='.$person_phid;
+ $name = pht('Lint Messages');
+
+ $menu->addMenuItemToLabel('activity',
+ id(new PhabricatorMenuItemView())
+ ->setIsExternal(true)
+ ->setHref($href)
+ ->setName($name)
+ ->setKey($name)
+ );
+
+ $event->setValue('menu', $menu);
+ }
+
+}
+
diff --git a/src/applications/files/PhabricatorImageTransformer.php b/src/applications/files/PhabricatorImageTransformer.php
index a073d14030..8e651eba69 100644
--- a/src/applications/files/PhabricatorImageTransformer.php
+++ b/src/applications/files/PhabricatorImageTransformer.php
@@ -1,299 +1,371 @@
<?php
final class PhabricatorImageTransformer {
public function executeMemeTransform(
PhabricatorFile $file,
$upper_text,
$lower_text) {
$image = $this->applyMemeTo($file, $upper_text, $lower_text);
return PhabricatorFile::newFromFileData(
$image,
array(
'name' => 'meme-'.$file->getName(),
));
}
public function executeThumbTransform(
PhabricatorFile $file,
$x,
$y) {
$image = $this->crudelyScaleTo($file, $x, $y);
return PhabricatorFile::newFromFileData(
$image,
array(
'name' => 'thumb-'.$file->getName(),
));
}
public function executeProfileTransform(
PhabricatorFile $file,
$x,
$min_y,
$max_y) {
$image = $this->crudelyCropTo($file, $x, $min_y, $max_y);
return PhabricatorFile::newFromFileData(
$image,
array(
'name' => 'profile-'.$file->getName(),
));
}
public function executePreviewTransform(
PhabricatorFile $file,
$size) {
$image = $this->generatePreview($file, $size);
return PhabricatorFile::newFromFileData(
$image,
array(
'name' => 'preview-'.$file->getName(),
));
}
+ public function executeConpherenceTransform(
+ PhabricatorFile $file,
+ $top,
+ $left,
+ $width,
+ $height
+ ) {
+
+ $image = $this->crasslyCropTo(
+ $file,
+ $top,
+ $left,
+ $width,
+ $height
+ );
+
+ return PhabricatorFile::newFromFileData(
+ $image,
+ array(
+ 'name' => 'conpherence-'.$file->getName(),
+ )
+ );
+ }
private function crudelyCropTo(PhabricatorFile $file, $x, $min_y, $max_y) {
$data = $file->loadFileData();
$img = imagecreatefromstring($data);
$sx = imagesx($img);
$sy = imagesy($img);
$scaled_y = ($x / $sx) * $sy;
if ($scaled_y > $max_y) {
// This image is very tall and thin.
$scaled_y = $max_y;
} else if ($scaled_y < $min_y) {
// This image is very short and wide.
$scaled_y = $min_y;
}
$img = $this->applyScaleTo(
$img,
$x,
$scaled_y);
return $this->saveImageDataInAnyFormat($img, $file->getMimeType());
}
+ private function crasslyCropTo(PhabricatorFile $file, $top, $left, $w, $h) {
+ $data = $file->loadFileData();
+ $src = imagecreatefromstring($data);
+ $dst = $this->getBlankDestinationFile($w, $h);
+
+ $scale = self::getScaleForCrop($file, $w, $h);
+ $orig_x = $left / $scale;
+ $orig_y = $top / $scale;
+ $orig_w = $w / $scale;
+ $orig_h = $h / $scale;
+
+ imagecopyresampled(
+ $dst,
+ $src,
+ 0, 0,
+ $orig_x, $orig_y,
+ $w, $h,
+ $orig_w, $orig_h
+ );
+
+ return $this->saveImageDataInAnyFormat($dst, $file->getMimeType());
+ }
+
+
/**
* Very crudely scale an image up or down to an exact size.
*/
private function crudelyScaleTo(PhabricatorFile $file, $dx, $dy) {
$data = $file->loadFileData();
$src = imagecreatefromstring($data);
$dst = $this->applyScaleTo($src, $dx, $dy);
return $this->saveImageDataInAnyFormat($dst, $file->getMimeType());
}
+ private function getBlankDestinationFile($dx, $dy) {
+ $dst = imagecreatetruecolor($dx, $dy);
+ imagesavealpha($dst, true);
+ imagefill($dst, 0, 0, imagecolorallocatealpha($dst, 255, 255, 255, 127));
+
+ return $dst;
+ }
+
private function applyScaleTo($src, $dx, $dy) {
$x = imagesx($src);
$y = imagesy($src);
$scale = min(($dx / $x), ($dy / $y), 1);
- $dst = imagecreatetruecolor($dx, $dy);
- imagesavealpha($dst, true);
- imagefill($dst, 0, 0, imagecolorallocatealpha($dst, 255, 255, 255, 127));
+ $dst = $this->getBlankDestinationFile($dx, $dy);
$sdx = $scale * $x;
$sdy = $scale * $y;
imagecopyresampled(
$dst,
$src,
($dx - $sdx) / 2, ($dy - $sdy) / 2,
0, 0,
$sdx, $sdy,
$x, $y);
return $dst;
}
public static function getPreviewDimensions(PhabricatorFile $file, $size) {
$data = $file->loadFileData();
$src = imagecreatefromstring($data);
$x = imagesx($src);
$y = imagesy($src);
$scale = min($size / $x, $size / $y, 1);
$dx = max($size / 4, $scale * $x);
$dy = max($size / 4, $scale * $y);
$sdx = $scale * $x;
$sdy = $scale * $y;
return array(
'x' => $x,
'y' => $y,
'dx' => $dx,
'dy' => $dy,
'sdx' => $sdx,
'sdy' => $sdy
);
}
+ public static function getScaleForCrop(
+ PhabricatorFile $file,
+ $des_width,
+ $des_height) {
+
+ $metadata = $file->getMetadata();
+ $width = $metadata[PhabricatorFile::METADATA_IMAGE_WIDTH];
+ $height = $metadata[PhabricatorFile::METADATA_IMAGE_HEIGHT];
+
+ if ($height < $des_height) {
+ $scale = $height / $des_height;
+ } else if ($width < $des_width) {
+ $scale = $width / $des_width;
+ } else {
+ $scale_x = $des_width / $width;
+ $scale_y = $des_height / $height;
+ $scale = max($scale_x, $scale_y);
+ }
+
+ return $scale;
+ }
private function generatePreview(PhabricatorFile $file, $size) {
$data = $file->loadFileData();
$src = imagecreatefromstring($data);
$dimensions = self::getPreviewDimensions($file, $size);
$x = $dimensions['x'];
$y = $dimensions['y'];
$dx = $dimensions['dx'];
$dy = $dimensions['dy'];
$sdx = $dimensions['sdx'];
$sdy = $dimensions['sdy'];
- $dst = imagecreatetruecolor($dx, $dy);
- imagesavealpha($dst, true);
- imagefill($dst, 0, 0, imagecolorallocatealpha($dst, 255, 255, 255, 127));
+ $dst = $this->getBlankDestinationFile($dx, $dy);
imagecopyresampled(
$dst,
$src,
($dx - $sdx) / 2, ($dy - $sdy) / 2,
0, 0,
$sdx, $sdy,
$x, $y);
return $this->saveImageDataInAnyFormat($dst, $file->getMimeType());
}
private function applyMemeTo(
PhabricatorFile $file,
$upper_text,
$lower_text) {
$data = $file->loadFileData();
$img = imagecreatefromstring($data);
$phabricator_root = dirname(phutil_get_library_root('phabricator'));
$font_root = $phabricator_root.'/resources/font/';
$font_path = $font_root.'tuffy.ttf';
if (Filesystem::pathExists($font_root.'impact.ttf')) {
$font_path = $font_root.'impact.ttf';
}
$text_color = imagecolorallocate($img, 255, 255, 255);
$border_color = imagecolorallocatealpha($img, 0, 0, 0, 110);
$border_width = 4;
$font_max = 200;
$font_min = 5;
for ($i = $font_max; $i > $font_min; $i--) {
$fit = $this->doesTextBoundingBoxFitInImage(
$img,
$upper_text,
$i,
$font_path);
if ($fit['doesfit']) {
$x = ($fit['imgwidth'] - $fit['txtwidth']) / 2;
$y = $fit['txtheight'] + 10;
$this->makeImageWithTextBorder($img,
$i,
$x,
$y,
$text_color,
$border_color,
$border_width,
$font_path,
$upper_text);
break;
}
}
for ($i = $font_max; $i > $font_min; $i--) {
$fit = $this->doesTextBoundingBoxFitInImage($img,
$lower_text, $i, $font_path);
if ($fit['doesfit']) {
$x = ($fit['imgwidth'] - $fit['txtwidth']) / 2;
$y = $fit['imgheight'] - 10;
$this->makeImageWithTextBorder(
$img,
$i,
$x,
$y,
$text_color,
$border_color,
$border_width,
$font_path,
$lower_text);
break;
}
}
return $this->saveImageDataInAnyFormat($img, $file->getMimeType());
}
private function makeImageWithTextBorder($img, $font_size, $x, $y,
$color, $stroke_color, $bw, $font, $text) {
$angle = 0;
$bw = abs($bw);
for ($c1 = $x - $bw; $c1 <= $x + $bw; $c1++) {
for ($c2 = $y - $bw; $c2 <= $y + $bw; $c2++) {
if (!(($c1 == $x - $bw || $x + $bw) &&
$c2 == $y - $bw || $c2 == $y + $bw)) {
$bg = imagettftext($img, $font_size,
$angle, $c1, $c2, $stroke_color, $font, $text);
}
}
}
imagettftext($img, $font_size, $angle,
$x , $y, $color , $font, $text);
}
private function doesTextBoundingBoxFitInImage($img,
$text, $font_size, $font_path) {
// Default Angle = 0
$angle = 0;
$bbox = imagettfbbox($font_size, $angle, $font_path, $text);
$text_height = abs($bbox[3] - $bbox[5]);
$text_width = abs($bbox[0] - $bbox[2]);
return array(
"doesfit" => ($text_height * 1.05 <= imagesy($img) / 2
&& $text_width * 1.05 <= imagesx($img)),
"txtwidth" => $text_width,
"txtheight" => $text_height,
"imgwidth" => imagesx($img),
"imgheight" => imagesy($img),
);
}
private function saveImageDataInAnyFormat($data, $preferred_mime = '') {
switch ($preferred_mime) {
case 'image/gif': // GIF doesn't support true color.
case 'image/png':
if (function_exists('imagepng')) {
ob_start();
imagepng($data);
return ob_get_clean();
}
break;
}
$img = null;
if (function_exists('imagejpeg')) {
ob_start();
imagejpeg($data);
$img = ob_get_clean();
} else if (function_exists('imagepng')) {
ob_start();
imagepng($data);
$img = ob_get_clean();
} else if (function_exists('imagegif')) {
ob_start();
imagegif($data);
$img = ob_get_clean();
} else {
throw new Exception("No image generation functions exist!");
}
return $img;
}
}
diff --git a/src/applications/files/engine/PhabricatorTestStorageEngine.php b/src/applications/files/engine/PhabricatorTestStorageEngine.php
new file mode 100644
index 0000000000..af45c6574a
--- /dev/null
+++ b/src/applications/files/engine/PhabricatorTestStorageEngine.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * Test storage engine. Does not actually store files. Used for unit tests.
+ *
+ * @group filestorage
+ */
+final class PhabricatorTestStorageEngine
+ extends PhabricatorFileStorageEngine {
+
+ private static $storage = array();
+ private static $nextHandle = 1;
+
+ public function getEngineIdentifier() {
+ return 'unit-test';
+ }
+
+ public function writeFile($data, array $params) {
+ AphrontWriteGuard::willWrite();
+ self::$storage[self::$nextHandle] = $data;
+ return self::$nextHandle++;
+ }
+
+ public function readFile($handle) {
+ if (isset(self::$storage[$handle])) {
+ return self::$storage[$handle];
+ }
+ throw new Exception("No such file with handle '{$handle}'!");
+ }
+
+ public function deleteFile($handle) {
+ AphrontWriteGuard::willWrite();
+ unset(self::$storage[$handle]);
+ }
+
+}
diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php
index 8a9f486644..4e28e4d3f0 100644
--- a/src/applications/files/storage/PhabricatorFile.php
+++ b/src/applications/files/storage/PhabricatorFile.php
@@ -1,564 +1,571 @@
<?php
final class PhabricatorFile extends PhabricatorFileDAO
implements PhabricatorPolicyInterface {
const STORAGE_FORMAT_RAW = 'raw';
const METADATA_IMAGE_WIDTH = 'width';
const METADATA_IMAGE_HEIGHT = 'height';
protected $phid;
protected $name;
protected $mimeType;
protected $byteSize;
protected $authorPHID;
protected $secretKey;
protected $contentHash;
protected $metadata = array();
protected $storageEngine;
protected $storageFormat;
protected $storageHandle;
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'metadata' => self::SERIALIZATION_JSON,
),
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
PhabricatorPHIDConstants::PHID_TYPE_FILE);
}
public static function readUploadedFileData($spec) {
if (!$spec) {
throw new Exception("No file was uploaded!");
}
$err = idx($spec, 'error');
if ($err) {
throw new PhabricatorFileUploadException($err);
}
$tmp_name = idx($spec, 'tmp_name');
$is_valid = @is_uploaded_file($tmp_name);
if (!$is_valid) {
throw new Exception("File is not an uploaded file.");
}
$file_data = Filesystem::readFile($tmp_name);
$file_size = idx($spec, 'size');
if (strlen($file_data) != $file_size) {
throw new Exception("File size disagrees with uploaded size.");
}
self::validateFileSize(strlen($file_data));
return $file_data;
}
public static function newFromPHPUpload($spec, array $params = array()) {
$file_data = self::readUploadedFileData($spec);
$file_name = nonempty(
idx($params, 'name'),
idx($spec, 'name'));
$params = array(
'name' => $file_name,
) + $params;
return self::newFromFileData($file_data, $params);
}
public static function newFromXHRUpload($data, array $params = array()) {
self::validateFileSize(strlen($data));
return self::newFromFileData($data, $params);
}
private static function validateFileSize($size) {
$limit = PhabricatorEnv::getEnvConfig('storage.upload-size-limit');
if (!$limit) {
return;
}
$limit = phabricator_parse_bytes($limit);
if ($size > $limit) {
throw new PhabricatorFileUploadException(-1000);
}
}
/**
* Given a block of data, try to load an existing file with the same content
* if one exists. If it does not, build a new file.
*
* This method is generally used when we have some piece of semi-trusted data
* like a diff or a file from a repository that we want to show to the user.
* We can't just dump it out because it may be dangerous for any number of
* reasons; instead, we need to serve it through the File abstraction so it
* ends up on the CDN domain if one is configured and so on. However, if we
* simply wrote a new file every time we'd potentially end up with a lot
* of redundant data in file storage.
*
* To solve these problems, we use file storage as a cache and reuse the
* same file again if we've previously written it.
*
* NOTE: This method unguards writes.
*
* @param string Raw file data.
* @param dict Dictionary of file information.
*/
public static function buildFromFileDataOrHash(
$data,
array $params = array()) {
$file = id(new PhabricatorFile())->loadOneWhere(
'name = %s AND contentHash = %s LIMIT 1',
self::normalizeFileName(idx($params, 'name')),
PhabricatorHash::digest($data));
if (!$file) {
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$file = PhabricatorFile::newFromFileData($data, $params);
unset($unguarded);
}
return $file;
}
public static function newFromFileData($data, array $params = array()) {
- $selector = PhabricatorEnv::newObjectFromConfig('storage.engine-selector');
- $engines = $selector->selectStorageEngines($data, $params);
+ if (isset($params['storageEngines'])) {
+ $engines = $params['storageEngines'];
+ } else {
+ $selector = PhabricatorEnv::newObjectFromConfig(
+ 'storage.engine-selector');
+ $engines = $selector->selectStorageEngines($data, $params);
+ }
+
+ assert_instances_of($engines, 'PhabricatorFileStorageEngine');
if (!$engines) {
throw new Exception("No valid storage engines are available!");
}
$file = new PhabricatorFile();
$data_handle = null;
$engine_identifier = null;
$exceptions = array();
foreach ($engines as $engine) {
$engine_class = get_class($engine);
try {
list($engine_identifier, $data_handle) = $file->writeToEngine(
$engine,
$data,
$params);
// We stored the file somewhere so stop trying to write it to other
// places.
break;
} catch (PhabricatorFileStorageConfigurationException $ex) {
// If an engine is outright misconfigured (or misimplemented), raise
// that immediately since it probably needs attention.
throw $ex;
} catch (Exception $ex) {
phlog($ex);
// If an engine doesn't work, keep trying all the other valid engines
// in case something else works.
$exceptions[$engine_class] = $ex;
}
}
if (!$data_handle) {
throw new PhutilAggregateException(
"All storage engines failed to write file:",
$exceptions);
}
$file_name = idx($params, 'name');
$file_name = self::normalizeFileName($file_name);
// If for whatever reason, authorPHID isn't passed as a param
// (always the case with newFromFileDownload()), store a ''
$authorPHID = idx($params, 'authorPHID');
$file->setName($file_name);
$file->setByteSize(strlen($data));
$file->setAuthorPHID($authorPHID);
$file->setContentHash(PhabricatorHash::digest($data));
$file->setStorageEngine($engine_identifier);
$file->setStorageHandle($data_handle);
// TODO: This is probably YAGNI, but allows for us to do encryption or
// compression later if we want.
$file->setStorageFormat(self::STORAGE_FORMAT_RAW);
if (isset($params['mime-type'])) {
$file->setMimeType($params['mime-type']);
} else {
$tmp = new TempFile();
Filesystem::writeFile($tmp, $data);
$file->setMimeType(Filesystem::getMimeType($tmp));
}
try {
$file->updateDimensions(false);
} catch (Exception $ex) {
// Do nothing
}
$file->save();
return $file;
}
public function migrateToEngine(PhabricatorFileStorageEngine $engine) {
if (!$this->getID() || !$this->getStorageHandle()) {
throw new Exception(
"You can not migrate a file which hasn't yet been saved.");
}
$data = $this->loadFileData();
$params = array(
'name' => $this->getName(),
);
list($new_identifier, $new_handle) = $this->writeToEngine(
$engine,
$data,
$params);
$old_engine = $this->instantiateStorageEngine();
$old_handle = $this->getStorageHandle();
$this->setStorageEngine($new_identifier);
$this->setStorageHandle($new_handle);
$this->save();
$old_engine->deleteFile($old_handle);
return $this;
}
private function writeToEngine(
PhabricatorFileStorageEngine $engine,
$data,
array $params) {
$engine_class = get_class($engine);
$data_handle = $engine->writeFile($data, $params);
if (!$data_handle || strlen($data_handle) > 255) {
// This indicates an improperly implemented storage engine.
throw new PhabricatorFileStorageConfigurationException(
"Storage engine '{$engine_class}' executed writeFile() but did ".
"not return a valid handle ('{$data_handle}') to the data: it ".
"must be nonempty and no longer than 255 characters.");
}
$engine_identifier = $engine->getEngineIdentifier();
if (!$engine_identifier || strlen($engine_identifier) > 32) {
throw new PhabricatorFileStorageConfigurationException(
"Storage engine '{$engine_class}' returned an improper engine ".
"identifier '{$engine_identifier}': it must be nonempty ".
"and no longer than 32 characters.");
}
return array($engine_identifier, $data_handle);
}
public static function newFromFileDownload($uri, array $params) {
$uri = new PhutilURI($uri);
$protocol = $uri->getProtocol();
switch ($protocol) {
case 'http':
case 'https':
break;
default:
// Make sure we are not accessing any file:// URIs or similar.
return null;
}
$timeout = 5;
list($file_data) = id(new HTTPSFuture($uri))
->setTimeout($timeout)
->resolvex();
return self::newFromFileData($file_data, $params);
}
public static function normalizeFileName($file_name) {
return preg_replace('/[^a-zA-Z0-9.~_-]/', '_', $file_name);
}
public function delete() {
$engine = $this->instantiateStorageEngine();
$ret = parent::delete();
$engine->deleteFile($this->getStorageHandle());
return $ret;
}
public function loadFileData() {
$engine = $this->instantiateStorageEngine();
$data = $engine->readFile($this->getStorageHandle());
switch ($this->getStorageFormat()) {
case self::STORAGE_FORMAT_RAW:
$data = $data;
break;
default:
throw new Exception("Unknown storage format.");
}
return $data;
}
public function getViewURI() {
if (!$this->getPHID()) {
throw new Exception(
"You must save a file before you can generate a view URI.");
}
$name = phutil_escape_uri($this->getName());
$path = '/file/data/'.$this->getSecretKey().'/'.$this->getPHID().'/'.$name;
return PhabricatorEnv::getCDNURI($path);
}
public function getInfoURI() {
return '/file/info/'.$this->getPHID().'/';
}
public function getBestURI() {
if ($this->isViewableInBrowser()) {
return $this->getViewURI();
} else {
return $this->getInfoURI();
}
}
public function getDownloadURI() {
$uri = id(new PhutilURI($this->getViewURI()))
->setQueryParam('download', true);
return (string) $uri;
}
public function getThumb60x45URI() {
$path = '/file/xform/thumb-60x45/'.$this->getPHID().'/'
.$this->getSecretKey().'/';
return PhabricatorEnv::getCDNURI($path);
}
public function getThumb160x120URI() {
$path = '/file/xform/thumb-160x120/'.$this->getPHID().'/'
.$this->getSecretKey().'/';
return PhabricatorEnv::getCDNURI($path);
}
public function getPreview220URI() {
$path = '/file/xform/preview-220/'.$this->getPHID().'/'
.$this->getSecretKey().'/';
return PhabricatorEnv::getCDNURI($path);
}
public function getThumb220x165URI() {
$path = '/file/xform/thumb-220x165/'.$this->getPHID().'/'
.$this->getSecretKey().'/';
return PhabricatorEnv::getCDNURI($path);
}
public function isViewableInBrowser() {
return ($this->getViewableMimeType() !== null);
}
public function isViewableImage() {
if (!$this->isViewableInBrowser()) {
return false;
}
$mime_map = PhabricatorEnv::getEnvConfig('files.image-mime-types');
$mime_type = $this->getMimeType();
return idx($mime_map, $mime_type);
}
public function isTransformableImage() {
// NOTE: The way the 'gd' extension works in PHP is that you can install it
// with support for only some file types, so it might be able to handle
// PNG but not JPEG. Try to generate thumbnails for whatever we can. Setup
// warns you if you don't have complete support.
$matches = null;
$ok = preg_match(
'@^image/(gif|png|jpe?g)@',
$this->getViewableMimeType(),
$matches);
if (!$ok) {
return false;
}
switch ($matches[1]) {
case 'jpg';
case 'jpeg':
return function_exists('imagejpeg');
break;
case 'png':
return function_exists('imagepng');
break;
case 'gif':
return function_exists('imagegif');
break;
default:
throw new Exception('Unknown type matched as image MIME type.');
}
}
public static function getTransformableImageFormats() {
$supported = array();
if (function_exists('imagejpeg')) {
$supported[] = 'jpg';
}
if (function_exists('imagepng')) {
$supported[] = 'png';
}
if (function_exists('imagegif')) {
$supported[] = 'gif';
}
return $supported;
}
protected function instantiateStorageEngine() {
return self::buildEngine($this->getStorageEngine());
}
public static function buildEngine($engine_identifier) {
$engines = self::buildAllEngines();
foreach ($engines as $engine) {
if ($engine->getEngineIdentifier() == $engine_identifier) {
return $engine;
}
}
throw new Exception(
"Storage engine '{$engine_identifier}' could not be located!");
}
public static function buildAllEngines() {
$engines = id(new PhutilSymbolLoader())
->setType('class')
->setConcreteOnly(true)
->setAncestorClass('PhabricatorFileStorageEngine')
->selectAndLoadSymbols();
$results = array();
foreach ($engines as $engine_class) {
$results[] = newv($engine_class['name'], array());
}
return $results;
}
public function getViewableMimeType() {
$mime_map = PhabricatorEnv::getEnvConfig('files.viewable-mime-types');
$mime_type = $this->getMimeType();
$mime_parts = explode(';', $mime_type);
$mime_type = trim(reset($mime_parts));
return idx($mime_map, $mime_type);
}
public function validateSecretKey($key) {
return ($key == $this->getSecretKey());
}
public function save() {
if (!$this->getSecretKey()) {
$this->setSecretKey($this->generateSecretKey());
}
return parent::save();
}
public function generateSecretKey() {
return Filesystem::readRandomCharacters(20);
}
public function updateDimensions($save = true) {
if (!$this->isViewableImage()) {
throw new Exception(
"This file is not a viewable image.");
}
if (!function_exists("imagecreatefromstring")) {
throw new Exception(
"Cannot retrieve image information.");
}
$data = $this->loadFileData();
$img = imagecreatefromstring($data);
if ($img === false) {
throw new Exception(
"Error when decoding image.");
}
$this->metadata[self::METADATA_IMAGE_WIDTH] = imagesx($img);
$this->metadata[self::METADATA_IMAGE_HEIGHT] = imagesy($img);
if ($save) {
$this->save();
}
return $this;
}
public static function getMetadataName($metadata) {
switch ($metadata) {
case self::METADATA_IMAGE_WIDTH:
$name = pht('Width');
break;
case self::METADATA_IMAGE_HEIGHT:
$name = pht('Height');
break;
default:
$name = ucfirst($metadata);
break;
}
return $name;
}
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
);
}
public function getPolicy($capability) {
// TODO: Implement proper per-object policies.
return PhabricatorPolicies::POLICY_USER;
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
}
diff --git a/src/applications/files/storage/__tests__/PhabricatorFileTestCase.php b/src/applications/files/storage/__tests__/PhabricatorFileTestCase.php
new file mode 100644
index 0000000000..334d3a92f1
--- /dev/null
+++ b/src/applications/files/storage/__tests__/PhabricatorFileTestCase.php
@@ -0,0 +1,61 @@
+<?php
+
+final class PhabricatorFileTestCase extends PhabricatorTestCase {
+
+ public function getPhabricatorTestCaseConfiguration() {
+ return array(
+ self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES => true,
+ );
+ }
+
+ public function testFileStorageReadWrite() {
+ $engine = new PhabricatorTestStorageEngine();
+
+ $data = Filesystem::readRandomCharacters(64);
+
+ $params = array(
+ 'name' => 'test.dat',
+ 'storageEngines' => array(
+ $engine,
+ ),
+ );
+
+ $file = PhabricatorFile::newFromFileData($data, $params);
+
+ // Test that the storage engine worked, and was the target of the write. We
+ // don't actually care what the data is (future changes may compress or
+ // encrypt it), just that it exists in the test storage engine.
+ $engine->readFile($file->getStorageHandle());
+
+ // Now test that we get the same data back out.
+ $this->assertEqual($data, $file->loadFileData());
+ }
+
+
+ public function testFileStorageDelete() {
+ $engine = new PhabricatorTestStorageEngine();
+
+ $data = Filesystem::readRandomCharacters(64);
+
+ $params = array(
+ 'name' => 'test.dat',
+ 'storageEngines' => array(
+ $engine,
+ ),
+ );
+
+ $file = PhabricatorFile::newFromFileData($data, $params);
+ $handle = $file->getStorageHandle();
+ $file->delete();
+
+ $caught = null;
+ try {
+ $engine->readFile($handle);
+ } catch (Exception $ex) {
+ $caught = $ex;
+ }
+
+ $this->assertEqual(true, $caught instanceof Exception);
+ }
+
+}
diff --git a/src/applications/maniphest/application/PhabricatorApplicationManiphest.php b/src/applications/maniphest/application/PhabricatorApplicationManiphest.php
index 787c5eb6f7..654d99f341 100644
--- a/src/applications/maniphest/application/PhabricatorApplicationManiphest.php
+++ b/src/applications/maniphest/application/PhabricatorApplicationManiphest.php
@@ -1,109 +1,115 @@
<?php
final class PhabricatorApplicationManiphest extends PhabricatorApplication {
public function getShortDescription() {
return 'Tasks and Bugs';
}
public function getBaseURI() {
return '/maniphest/';
}
public function isEnabled() {
return PhabricatorEnv::getEnvConfig('maniphest.enabled');
}
public function getIconName() {
return 'maniphest';
}
public function getApplicationGroup() {
return self::GROUP_CORE;
}
public function getApplicationOrder() {
return 0.110;
}
public function getFactObjectsForAnalysis() {
return array(
new ManiphestTask(),
);
}
public function getQuickCreateURI() {
return $this->getBaseURI().'task/create/';
}
+ public function getEventListeners() {
+ return array(
+ new ManiphestPeopleMenuEventListener()
+ );
+ }
+
public function getRoutes() {
return array(
'/T(?P<id>[1-9]\d*)' => 'ManiphestTaskDetailController',
'/maniphest/' => array(
'' => 'ManiphestTaskListController',
'view/(?P<view>\w+)/' => 'ManiphestTaskListController',
'report/(?:(?P<view>\w+)/)?' => 'ManiphestReportController',
'batch/' => 'ManiphestBatchEditController',
'task/' => array(
'create/' => 'ManiphestTaskEditController',
'edit/(?P<id>[1-9]\d*)/' => 'ManiphestTaskEditController',
'descriptionchange/(?:(?P<id>[1-9]\d*)/)?' =>
'ManiphestTaskDescriptionChangeController',
'descriptionpreview/' =>
'ManiphestTaskDescriptionPreviewController',
),
'transaction/' => array(
'save/' => 'ManiphestTransactionSaveController',
'preview/(?P<id>[1-9]\d*)/'
=> 'ManiphestTransactionPreviewController',
),
'export/(?P<key>[^/]+)/' => 'ManiphestExportController',
'subpriority/' => 'ManiphestSubpriorityController',
'custom/' => array(
'' => 'ManiphestSavedQueryListController',
'edit/(?:(?P<id>[1-9]\d*)/)?' => 'ManiphestSavedQueryEditController',
'delete/(?P<id>[1-9]\d*)/' => 'ManiphestSavedQueryDeleteController',
),
),
);
}
public function loadStatus(PhabricatorUser $user) {
$status = array();
$query = id(new ManiphestTaskQuery())
->withStatus(ManiphestTaskQuery::STATUS_OPEN)
->withPriority(ManiphestTaskPriority::PRIORITY_UNBREAK_NOW)
->setLimit(1)
->setCalculateRows(true);
$query->execute();
$count = $query->getRowCount();
$type = $count
? PhabricatorApplicationStatusView::TYPE_NEEDS_ATTENTION
: PhabricatorApplicationStatusView::TYPE_EMPTY;
$status[] = id(new PhabricatorApplicationStatusView())
->setType($type)
->setText(pht('%d Unbreak Now Task(s)!', $count))
->setCount($count);
$query = id(new ManiphestTaskQuery())
->withStatus(ManiphestTaskQuery::STATUS_OPEN)
->withOwners(array($user->getPHID()))
->setLimit(1)
->setCalculateRows(true);
$query->execute();
$count = $query->getRowCount();
$type = $count
? PhabricatorApplicationStatusView::TYPE_INFO
: PhabricatorApplicationStatusView::TYPE_EMPTY;
$status[] = id(new PhabricatorApplicationStatusView())
->setType($type)
->setText(pht('%d Assigned Task(s)', $count));
return $status;
}
}
diff --git a/src/applications/maniphest/event/ManiphestPeopleMenuEventListener.php b/src/applications/maniphest/event/ManiphestPeopleMenuEventListener.php
new file mode 100644
index 0000000000..c7008e6ed9
--- /dev/null
+++ b/src/applications/maniphest/event/ManiphestPeopleMenuEventListener.php
@@ -0,0 +1,36 @@
+<?php
+
+final class ManiphestPeopleMenuEventListener extends PhutilEventListener {
+
+ public function register() {
+ $this->listen(PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU);
+ }
+
+ public function handleEvent(PhutilEvent $event) {
+ switch ($event->getType()) {
+ case PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU:
+ $this->handleMenuEvent($event);
+ break;
+ }
+ }
+
+ private function handleMenuEvent($event) {
+ $viewer = $event->getUser();
+ $menu = $event->getValue('menu');
+ $person_phid = $event->getValue('person')->getPHID();
+
+ $href = '/maniphest/view/action/?users='.$person_phid;
+ $name = pht('Tasks');
+
+ $menu->addMenuItemToLabel('activity',
+ id(new PhabricatorMenuItemView())
+ ->setIsExternal(true)
+ ->setHref($href)
+ ->setName($name)
+ ->setKey($name)
+ );
+
+ $event->setValue('menu', $menu);
+ }
+
+}
diff --git a/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php b/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php
index da9f6438be..a0b4e1d592 100644
--- a/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php
+++ b/src/applications/oauthserver/controller/PhabricatorOAuthServerAuthController.php
@@ -1,209 +1,207 @@
<?php
/**
* @group oauthserver
*/
final class PhabricatorOAuthServerAuthController
extends PhabricatorAuthController {
public function shouldRequireLogin() {
return true;
}
public function processRequest() {
$request = $this->getRequest();
$current_user = $request->getUser();
$server = new PhabricatorOAuthServer();
$client_phid = $request->getStr('client_id');
- $scope = $request->getStr('scope');
+ $scope = $request->getStr('scope', array());
$redirect_uri = $request->getStr('redirect_uri');
$state = $request->getStr('state');
$response_type = $request->getStr('response_type');
$response = new PhabricatorOAuthResponse();
// state is an opaque value the client sent us for their own purposes
// we just need to send it right back to them in the response!
if ($state) {
$response->setState($state);
}
if (!$client_phid) {
$response->setError('invalid_request');
$response->setErrorDescription(
'Required parameter client_id not specified.'
);
return $response;
}
$server->setUser($current_user);
// one giant try / catch around all the exciting database stuff so we
// can return a 'server_error' response if something goes wrong!
try {
$client = id(new PhabricatorOAuthServerClient())
->loadOneWhere('phid = %s', $client_phid);
if (!$client) {
$response->setError('invalid_request');
$response->setErrorDescription(
'Client with id '.$client_phid.' not found.'
);
return $response;
}
$server->setClient($client);
if ($redirect_uri) {
$client_uri = new PhutilURI($client->getRedirectURI());
$redirect_uri = new PhutilURI($redirect_uri);
if (!($server->validateSecondaryRedirectURI($redirect_uri,
$client_uri))) {
$response->setError('invalid_request');
$response->setErrorDescription(
'The specified redirect URI is invalid. The redirect URI '.
'must be a fully-qualified domain with no fragments and '.
'must have the same domain and at least the same query '.
'parameters as the redirect URI the client registered.'
);
return $response;
}
$uri = $redirect_uri;
- $access_token_uri = $uri;
} else {
$uri = new PhutilURI($client->getRedirectURI());
- $access_token_uri = null;
}
// we've now validated this request enough overall such that we
// can safely redirect to the client with the response
$response->setClientURI($uri);
if (empty($response_type)) {
$response->setError('invalid_request');
$response->setErrorDescription(
'Required parameter response_type not specified.'
);
return $response;
}
if ($response_type != 'code') {
$response->setError('unsupported_response_type');
$response->setErrorDescription(
'The authorization server does not support obtaining an '.
'authorization code using the specified response_type. '.
'You must specify the response_type as "code".'
);
return $response;
}
if ($scope) {
if (!PhabricatorOAuthServerScope::validateScopesList($scope)) {
$response->setError('invalid_scope');
$response->setErrorDescription(
'The requested scope is invalid, unknown, or malformed.'
);
return $response;
}
$scope = PhabricatorOAuthServerScope::scopesListToDict($scope);
}
list($is_authorized,
$authorization) = $server->userHasAuthorizedClient($scope);
if ($is_authorized) {
$return_auth_code = true;
$unguarded_write = AphrontWriteGuard::beginScopedUnguardedWrites();
} else if ($request->isFormPost()) {
$scope = PhabricatorOAuthServerScope::getScopesFromRequest($request);
if ($authorization) {
$authorization->setScope($scope)->save();
} else {
$authorization = $server->authorizeClient($scope);
}
$return_auth_code = true;
$unguarded_write = null;
} else {
$return_auth_code = false;
$unguarded_write = null;
}
if ($return_auth_code) {
// step 1 -- generate authorization code
$auth_code =
- $server->generateAuthorizationCode($access_token_uri);
+ $server->generateAuthorizationCode($uri);
// step 2 return it
$content = array(
'code' => $auth_code->getCode(),
'scope' => $authorization->getScopeString(),
);
$response->setContent($content);
return $response;
}
unset($unguarded_write);
} catch (Exception $e) {
// Note we could try harder to determine between a server_error
// vs temporarily_unavailable. Good enough though.
$response->setError('server_error');
$response->setErrorDescription(
'The authorization server encountered an unexpected condition '.
'which prevented it from fulfilling the request. '
);
return $response;
}
// display time -- make a nice form for the user to grant the client
// access to the granularity specified by $scope
$name = phutil_escape_html($client->getName());
$title = 'Authorize ' . $name . '?';
$panel = new AphrontPanelView();
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->setHeader($title);
$description =
"Do want to authorize {$name} to access your ".
"Phabricator account data?";
if ($scope) {
if ($authorization) {
$desired_scopes = array_merge($scope,
$authorization->getScope());
} else {
$desired_scopes = $scope;
}
if (!PhabricatorOAuthServerScope::validateScopesDict($desired_scopes)) {
$response->setError('invalid_scope');
$response->setErrorDescription(
'The requested scope is invalid, unknown, or malformed.'
);
return $response;
}
} else {
$desired_scopes = array(
PhabricatorOAuthServerScope::SCOPE_WHOAMI => 1,
PhabricatorOAuthServerScope::SCOPE_OFFLINE_ACCESS => 1
);
}
$cancel_uri = clone $uri;
$cancel_params = array(
'error' => 'access_denied',
'error_description' =>
'The resource owner (aka the user) denied the request.'
);
$cancel_uri->setQueryParams($cancel_params);
$form = id(new AphrontFormView())
->setUser($current_user)
->appendChild(
id(new AphrontFormStaticControl())
->setValue($description)
)
->appendChild(
PhabricatorOAuthServerScope::getCheckboxControl($desired_scopes)
)
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Authorize')
->addCancelButton($cancel_uri)
);
$panel->appendChild($form);
return $this->buildStandardPageResponse(
$panel,
array('title' => $title));
}
}
diff --git a/src/applications/people/controller/PhabricatorPeopleProfileController.php b/src/applications/people/controller/PhabricatorPeopleProfileController.php
index 576758f2e9..f88c7dfa0e 100644
--- a/src/applications/people/controller/PhabricatorPeopleProfileController.php
+++ b/src/applications/people/controller/PhabricatorPeopleProfileController.php
@@ -1,230 +1,243 @@
<?php
final class PhabricatorPeopleProfileController
extends PhabricatorPeopleController {
private $username;
private $page;
private $profileUser;
public function willProcessRequest(array $data) {
$this->username = idx($data, 'username');
$this->page = idx($data, 'page');
}
public function getProfileUser() {
return $this->profileUser;
}
+ private function getMainFilters($username) {
+ return array(
+ array(
+ 'key' => 'feed',
+ 'name' => pht('Feed'),
+ 'href' => '/p/'.$username.'/feed/'
+ ),
+ array(
+ 'key' => 'about',
+ 'name' => pht('About'),
+ 'href' => '/p/'.$username.'/about/'
+ )
+ );
+ }
+
public function processRequest() {
$viewer = $this->getRequest()->getUser();
$user = id(new PhabricatorUser())->loadOneWhere(
'userName = %s',
$this->username);
if (!$user) {
return new Aphront404Response();
}
$this->profileUser = $user;
require_celerity_resource('phabricator-profile-css');
$profile = id(new PhabricatorUserProfile())->loadOneWhere(
'userPHID = %s',
$user->getPHID());
if (!$profile) {
$profile = new PhabricatorUserProfile();
}
$username = phutil_escape_uri($user->getUserName());
- $external_arrow = "\xE2\x86\x97";
-
- $conpherence_uri =
- new PhutilURI('/conpherence/new/?participant='.$user->getPHID());
- $nav = new AphrontSideNavFilterView();
- $nav->setBaseURI(new PhutilURI('/p/'.$username.'/'));
- $nav->addFilter('feed', 'Feed');
- $nav->addMenuItem(
- id(new PhabricatorMenuItemView())
- ->setName(pht('Conpherence').' '.$external_arrow)
- ->setHref($conpherence_uri)
- );
- $nav->addFilter('about', 'About');
- $nav->addLabel('Activity');
-
- $nav->addFilter(
- null,
- "Revisions {$external_arrow}",
- '/differential/filter/revisions/'.$username.'/');
-
- $nav->addFilter(
- null,
- "Tasks {$external_arrow}",
- '/maniphest/view/action/?users='.$user->getPHID());
-
- $nav->addFilter(
- null,
- "Commits {$external_arrow}",
- '/audit/view/author/'.$username.'/');
+ $menu = new PhabricatorMenuView();
+ foreach ($this->getMainFilters($username) as $filter) {
+ $menu->newLink($filter['name'], $filter['href'], $filter['key']);
+ }
- $nav->addFilter(
- null,
- "Lint Messages {$external_arrow}",
- '/diffusion/lint/?owner[0]='.$user->getPHID());
+ $menu->newLabel(pht('Activity'), 'activity');
+ // NOTE: applications install the various links through PhabricatorEvent
+ // listeners
$oauths = id(new PhabricatorUserOAuthInfo())->loadAllWhere(
'userID = %d',
$user->getID());
$oauths = mpull($oauths, null, 'getOAuthProvider');
$providers = PhabricatorOAuthProvider::getAllProviders();
$added_label = false;
foreach ($providers as $provider) {
if (!$provider->isProviderEnabled()) {
continue;
}
$provider_key = $provider->getProviderKey();
if (!isset($oauths[$provider_key])) {
continue;
}
- $name = $provider->getProviderName().' Profile';
+ $name = pht('%s Profile', $provider->getProviderName());
$href = $oauths[$provider_key]->getAccountURI();
if ($href) {
if (!$added_label) {
- $nav->addLabel('Linked Accounts');
+ $menu->newLabel(pht('Linked Accounts'), 'linked_accounts');
$added_label = true;
}
- $nav->addFilter(null, $name.' '.$external_arrow, $href);
+ $menu->addMenuItem(
+ id(new PhabricatorMenuItemView())
+ ->setIsExternal(true)
+ ->setName($name)
+ ->setHref($href)
+ ->setType(PhabricatorMenuItemView::TYPE_LINK)
+ );
}
}
+ $event = new PhabricatorEvent(
+ PhabricatorEventType::TYPE_PEOPLE_DIDRENDERMENU,
+ array(
+ 'menu' => $menu,
+ 'person' => $user,
+ ));
+ $event->setUser($viewer);
+ PhutilEventEngine::dispatchEvent($event);
+ $nav = AphrontSideNavFilterView::newFromMenu($event->getValue('menu'));
+
$this->page = $nav->selectFilter($this->page, 'feed');
switch ($this->page) {
case 'feed':
$content = $this->renderUserFeed($user);
break;
case 'about':
$content = $this->renderBasicInformation($user, $profile);
break;
default:
throw new Exception("Unknown page '{$this->page}'!");
}
$picture = $user->loadProfileImageURI();
$header = new PhabricatorProfileHeaderView();
$header
->setProfilePicture($picture)
->setName($user->getUserName().' ('.$user->getRealName().')')
->setDescription($profile->getTitle());
if ($user->getIsDisabled()) {
$header->setStatus('Disabled');
} else {
$statuses = id(new PhabricatorUserStatus())->loadCurrentStatuses(
array($user->getPHID()));
if ($statuses) {
$header->setStatus(reset($statuses)->getTerseSummary($viewer));
}
}
$nav->appendChild($header);
$content = '<div style="padding: 1em;">'.$content.'</div>';
$header->appendChild($content);
if ($user->getPHID() == $viewer->getPHID()) {
- $nav->addFilter(null, 'Edit Profile...', '/settings/panel/profile/');
+ $nav->addFilter(
+ null,
+ pht('Edit Profile...'),
+ '/settings/panel/profile/'
+ );
}
if ($viewer->getIsAdmin()) {
$nav->addFilter(
null,
- 'Administrate User...',
- '/people/edit/'.$user->getID().'/');
+ pht('Administrate User...'),
+ '/people/edit/'.$user->getID().'/'
+ );
}
return $this->buildApplicationPage(
$nav,
array(
'title' => $user->getUsername(),
));
}
private function renderBasicInformation($user, $profile) {
$blurb = nonempty(
$profile->getBlurb(),
- '//Nothing is known about this rare specimen.//');
+ '//'.
+ pht('Nothing is known about this rare specimen.')
+ .'//'
+ );
$engine = PhabricatorMarkupEngine::newProfileMarkupEngine();
$blurb = phutil_safe_html($engine->markupText($blurb));
$viewer = $this->getRequest()->getUser();
$content =
'<div class="phabricator-profile-info-group">
<h1 class="phabricator-profile-info-header">Basic Information</h1>
<div class="phabricator-profile-info-pane">
<table class="phabricator-profile-info-table">
<tr>
<th>PHID</th>
<td>'.phutil_escape_html($user->getPHID()).'</td>
</tr>
<tr>
<th>User Since</th>
<td>'.phabricator_datetime($user->getDateCreated(),
$viewer).
'</td>
</tr>
</table>
</div>
</div>';
$content .=
'<div class="phabricator-profile-info-group">
<h1 class="phabricator-profile-info-header">Flavor Text</h1>
<div class="phabricator-profile-info-pane">
<table class="phabricator-profile-info-table">
<tr>
<th>Blurb</th>
<td>'.$blurb.'</td>
</tr>
</table>
</div>
</div>';
return $content;
}
private function renderUserFeed(PhabricatorUser $user) {
$viewer = $this->getRequest()->getUser();
$query = new PhabricatorFeedQuery();
$query->setFilterPHIDs(
array(
$user->getPHID(),
));
$query->setLimit(100);
$query->setViewer($viewer);
$stories = $query->execute();
$builder = new PhabricatorFeedBuilder($stories);
$builder->setUser($viewer);
$view = $builder->buildView();
return
'<div class="phabricator-profile-info-group">
<h1 class="phabricator-profile-info-header">Activity Feed</h1>
<div class="phabricator-profile-info-pane">
'.$view->render().'
</div>
</div>';
}
}
diff --git a/src/applications/phid/handle/PhabricatorObjectHandleData.php b/src/applications/phid/handle/PhabricatorObjectHandleData.php
index 52c1bb7d0c..67eaaf8e63 100644
--- a/src/applications/phid/handle/PhabricatorObjectHandleData.php
+++ b/src/applications/phid/handle/PhabricatorObjectHandleData.php
@@ -1,663 +1,660 @@
<?php
final class PhabricatorObjectHandleData {
private $phids;
private $viewer;
public function __construct(array $phids) {
$this->phids = array_unique($phids);
}
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
}
public static function loadOneHandle($phid, $viewer = null) {
$query = new PhabricatorObjectHandleData(array($phid));
if ($viewer) {
$query->setViewer($viewer);
}
$handles = $query->loadHandles();
return $handles[$phid];
}
public function loadObjects() {
$types = phid_group_by_type($this->phids);
$objects = array();
foreach ($types as $type => $phids) {
$objects += $this->loadObjectsOfType($type, $phids);
}
return $objects;
}
private function loadObjectsOfType($type, array $phids) {
switch ($type) {
case PhabricatorPHIDConstants::PHID_TYPE_USER:
$user_dao = new PhabricatorUser();
$users = $user_dao->loadAllWhere(
'phid in (%Ls)',
$phids);
return mpull($users, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_CMIT:
$commit_dao = new PhabricatorRepositoryCommit();
$commits = $commit_dao->putInSet(new LiskDAOSet())->loadAllWhere(
'phid IN (%Ls)',
$phids);
return mpull($commits, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_TASK:
$task_dao = new ManiphestTask();
$tasks = $task_dao->loadAllWhere(
'phid IN (%Ls)',
$phids);
return mpull($tasks, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_CONF:
$config_dao = new PhabricatorConfigEntry();
$entries = $config_dao->loadAllWhere(
'phid IN (%Ls)',
$phids);
return mpull($entries, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_FILE:
$object = new PhabricatorFile();
$files = $object->loadAllWhere('phid IN (%Ls)', $phids);
return mpull($files, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_PROJ:
$object = new PhabricatorProject();
if ($this->viewer) {
$projects = id(new PhabricatorProjectQuery())
->setViewer($this->viewer)
->withPHIDs($phids)
->execute();
} else {
$projects = $object->loadAllWhere('phid IN (%Ls)', $phids);
}
return mpull($projects, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_REPO:
$object = new PhabricatorRepository();
$repositories = $object->loadAllWhere('phid in (%Ls)', $phids);
return mpull($repositories, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_OPKG:
$object = new PhabricatorOwnersPackage();
$packages = $object->loadAllWhere('phid in (%Ls)', $phids);
return mpull($packages, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_APRJ:
$project_dao = new PhabricatorRepositoryArcanistProject();
$projects = $project_dao->loadAllWhere(
'phid IN (%Ls)',
$phids);
return mpull($projects, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_MLST:
$object = new PhabricatorMetaMTAMailingList();
$lists = $object->loadAllWhere('phid IN (%Ls)', $phids);
return mpull($lists, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_DREV:
$revision_dao = new DifferentialRevision();
$revisions = $revision_dao->loadAllWhere(
'phid IN (%Ls)',
$phids);
return mpull($revisions, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_WIKI:
$document_dao = new PhrictionDocument();
$documents = $document_dao->loadAllWhere(
'phid IN (%Ls)',
$phids);
return mpull($documents, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_QUES:
$questions = id(new PonderQuestionQuery())
->setViewer($this->viewer)
->withPHIDs($phids)
->execute();
return mpull($questions, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_MOCK:
$mocks = id(new PholioMockQuery())
->setViewer($this->viewer)
->withPHIDs($phids)
->execute();
return mpull($mocks, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_XACT:
$subtypes = array();
foreach ($phids as $phid) {
$subtypes[phid_get_subtype($phid)][] = $phid;
}
$xactions = array();
foreach ($subtypes as $subtype => $subtype_phids) {
// TODO: Do this magically.
switch ($subtype) {
case PhabricatorPHIDConstants::PHID_TYPE_MOCK:
$results = id(new PholioTransactionQuery())
->setViewer($this->viewer)
->withPHIDs($subtype_phids)
->execute();
$xactions += mpull($results, null, 'getPHID');
break;
case PhabricatorPHIDConstants::PHID_TYPE_MCRO:
$results = id(new PhabricatorMacroTransactionQuery())
->setViewer($this->viewer)
->withPHIDs($subtype_phids)
->execute();
$xactions += mpull($results, null, 'getPHID');
break;
}
}
return mpull($xactions, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_MCRO:
$macros = id(new PhabricatorFileImageMacro())->loadAllWhere(
'phid IN (%Ls)',
$phids);
return mpull($macros, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_PSTE:
$pastes = id(new PhabricatorPasteQuery())
->withPHIDs($phids)
->setViewer($this->viewer)
->execute();
return mpull($pastes, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_BLOG:
$blogs = id(new PhameBlogQuery())
->withPHIDs($phids)
->setViewer($this->viewer)
->execute();
return mpull($blogs, null, 'getPHID');
case PhabricatorPHIDConstants::PHID_TYPE_POST:
$posts = id(new PhamePostQuery())
->withPHIDs($phids)
->setViewer($this->viewer)
->execute();
return mpull($posts, null, 'getPHID');
}
}
public function loadHandles() {
$types = phid_group_by_type($this->phids);
$handles = array();
$external_loaders = PhabricatorEnv::getEnvConfig('phid.external-loaders');
foreach ($types as $type => $phids) {
$objects = $this->loadObjectsOfType($type, $phids);
switch ($type) {
case PhabricatorPHIDConstants::PHID_TYPE_MAGIC:
// Black magic!
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
switch ($phid) {
case ManiphestTaskOwner::OWNER_UP_FOR_GRABS:
$handle->setName('Up For Grabs');
$handle->setFullName('upforgrabs (Up For Grabs)');
$handle->setComplete(true);
break;
case ManiphestTaskOwner::PROJECT_NO_PROJECT:
$handle->setName('No Project');
$handle->setFullName('noproject (No Project)');
$handle->setComplete(true);
break;
default:
$handle->setName('Foul Magicks');
break;
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_USER:
$image_phids = mpull($objects, 'getProfileImagePHID');
$image_phids = array_unique(array_filter($image_phids));
$images = array();
if ($image_phids) {
$images = id(new PhabricatorFile())->loadAllWhere(
'phid IN (%Ls)',
$image_phids);
$images = mpull($images, 'getBestURI', 'getPHID');
}
$statuses = id(new PhabricatorUserStatus())->loadCurrentStatuses(
$phids);
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown User');
} else {
$user = $objects[$phid];
$handle->setName($user->getUsername());
$handle->setURI('/p/'.$user->getUsername().'/');
$handle->setFullName(
$user->getUsername().' ('.$user->getRealName().')');
$handle->setAlternateID($user->getID());
$handle->setComplete(true);
if (isset($statuses[$phid])) {
$handle->setStatus($statuses[$phid]->getTextStatus());
if ($this->viewer) {
$handle->setTitle(
$statuses[$phid]->getTerseSummary($this->viewer));
}
}
$handle->setDisabled($user->getIsDisabled());
$img_uri = idx($images, $user->getProfileImagePHID());
if ($img_uri) {
$handle->setImageURI($img_uri);
} else {
$handle->setImageURI(
PhabricatorUser::getDefaultProfileImageURI());
}
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_MLST:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Mailing List');
} else {
$list = $objects[$phid];
$handle->setName($list->getName());
$handle->setURI($list->getURI());
$handle->setFullName($list->getName());
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_DREV:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Revision');
} else {
$rev = $objects[$phid];
$handle->setName($rev->getTitle());
$handle->setURI('/D'.$rev->getID());
$handle->setFullName('D'.$rev->getID().': '.$rev->getTitle());
$handle->setComplete(true);
$status = $rev->getStatus();
if (($status == ArcanistDifferentialRevisionStatus::CLOSED) ||
($status == ArcanistDifferentialRevisionStatus::ABANDONED)) {
$closed = PhabricatorObjectHandleStatus::STATUS_CLOSED;
$handle->setStatus($closed);
}
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_CMIT:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
$repository = null;
if (!empty($objects[$phid])) {
$repository = $objects[$phid]->loadOneRelative(
new PhabricatorRepository(),
'id',
'getRepositoryID');
}
if (!$repository) {
$handle->setName('Unknown Commit');
} else {
$commit = $objects[$phid];
$callsign = $repository->getCallsign();
$commit_identifier = $commit->getCommitIdentifier();
// In case where the repository for the commit was deleted,
// we don't have info about the repository anymore.
if ($repository) {
$name = $repository->formatCommitName($commit_identifier);
$handle->setName($name);
} else {
$handle->setName('Commit '.'r'.$callsign.$commit_identifier);
}
$handle->setURI('/r'.$callsign.$commit_identifier);
$handle->setFullName('r'.$callsign.$commit_identifier);
$handle->setTimestamp($commit->getEpoch());
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_TASK:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Task');
} else {
$task = $objects[$phid];
$handle->setName($task->getTitle());
$handle->setURI('/T'.$task->getID());
$handle->setFullName('T'.$task->getID().': '.$task->getTitle());
$handle->setComplete(true);
$handle->setAlternateID($task->getID());
if ($task->getStatus() != ManiphestTaskStatus::STATUS_OPEN) {
$closed = PhabricatorObjectHandleStatus::STATUS_CLOSED;
$handle->setStatus($closed);
}
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_CONF:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Config Entry');
} else {
$entry = $objects[$phid];
$handle->setName($entry->getKey());
$handle->setURI('/config/edit/'.$entry->getKey());
$handle->setFullName($entry->getKey());
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_FILE:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown File');
} else {
$file = $objects[$phid];
$handle->setName($file->getName());
$handle->setURI($file->getBestURI());
$handle->setComplete(true);
- if ($file->isViewableImage()) {
- $handle->setImageURI($file->getBestURI());
- }
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_PROJ:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Project');
} else {
$project = $objects[$phid];
$handle->setName($project->getName());
$handle->setURI('/project/view/'.$project->getID().'/');
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_REPO:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Repository');
} else {
$repository = $objects[$phid];
$handle->setName($repository->getCallsign());
$handle->setURI('/diffusion/'.$repository->getCallsign().'/');
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_OPKG:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Package');
} else {
$package = $objects[$phid];
$handle->setName($package->getName());
$handle->setURI('/owners/package/'.$package->getID().'/');
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_APRJ:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Arcanist Project');
} else {
$project = $objects[$phid];
$handle->setName($project->getName());
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_WIKI:
$document_dao = new PhrictionDocument();
$content_dao = new PhrictionContent();
$conn = $document_dao->establishConnection('r');
$documents = queryfx_all(
$conn,
'SELECT * FROM %T document JOIN %T content
ON document.contentID = content.id
WHERE document.phid IN (%Ls)',
$document_dao->getTableName(),
$content_dao->getTableName(),
$phids);
$documents = ipull($documents, null, 'phid');
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($documents[$phid])) {
$handle->setName('Unknown Document');
} else {
$info = $documents[$phid];
$handle->setName($info['title']);
$handle->setURI(PhrictionDocument::getSlugURI($info['slug']));
$handle->setComplete(true);
if ($info['status'] != PhrictionDocumentStatus::STATUS_EXISTS) {
$closed = PhabricatorObjectHandleStatus::STATUS_CLOSED;
$handle->setStatus($closed);
}
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_QUES:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Ponder Question');
} else {
$question = $objects[$phid];
$handle->setName(phutil_utf8_shorten($question->getTitle(), 60));
$handle->setURI(new PhutilURI('/Q' . $question->getID()));
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_PSTE:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Paste');
} else {
$paste = $objects[$phid];
$handle->setName($paste->getTitle());
$handle->setFullName($paste->getFullName());
$handle->setURI('/P'.$paste->getID());
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_BLOG:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Blog');
} else {
$blog = $objects[$phid];
$handle->setName($blog->getName());
$handle->setFullName($blog->getName());
$handle->setURI('/phame/blog/view/'.$blog->getID().'/');
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_POST:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Post');
} else {
$post = $objects[$phid];
$handle->setName($post->getTitle());
$handle->setFullName($post->getTitle());
$handle->setURI('/phame/post/view/'.$post->getID().'/');
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_MOCK:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Mock');
} else {
$mock = $objects[$phid];
$handle->setName($mock->getName());
$handle->setFullName('M'.$mock->getID().': '.$mock->getName());
$handle->setURI('/M'.$mock->getID());
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
case PhabricatorPHIDConstants::PHID_TYPE_MCRO:
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setType($type);
if (empty($objects[$phid])) {
$handle->setName('Unknown Macro');
} else {
$macro = $objects[$phid];
$handle->setName($macro->getName());
$handle->setFullName('Image Macro "'.$macro->getName().'"');
$handle->setURI('/macro/view/'.$macro->getID().'/');
$handle->setComplete(true);
}
$handles[$phid] = $handle;
}
break;
default:
$loader = null;
if (isset($external_loaders[$type])) {
$loader = $external_loaders[$type];
} else if (isset($external_loaders['*'])) {
$loader = $external_loaders['*'];
}
if ($loader) {
$object = newv($loader, array());
assert_instances_of(array($type => $object), 'ObjectHandleLoader');
$handles += $object->loadHandles($phids);
break;
}
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setType($type);
$handle->setPHID($phid);
$handle->setName('Unknown Object');
$handle->setFullName('An Unknown Object');
$handles[$phid] = $handle;
}
break;
}
}
return $handles;
}
}
diff --git a/src/applications/pholio/application/PhabricatorApplicationPholio.php b/src/applications/pholio/application/PhabricatorApplicationPholio.php
index 5948f43c3d..10e4cafb07 100644
--- a/src/applications/pholio/application/PhabricatorApplicationPholio.php
+++ b/src/applications/pholio/application/PhabricatorApplicationPholio.php
@@ -1,50 +1,51 @@
<?php
/**
* @group pholio
*/
final class PhabricatorApplicationPholio extends PhabricatorApplication {
public function getBaseURI() {
return '/pholio/';
}
public function getShortDescription() {
return 'Design Review';
}
public function getIconName() {
return 'pholio';
}
public function getTitleGlyph() {
return "\xE2\x9D\xA6";
}
public function getFlavorText() {
return pht('Things before they were cool.');
}
public function getApplicationGroup() {
// TODO: Move to CORE, this just keeps it out of the side menu.
return self::GROUP_COMMUNICATION;
}
public function isBeta() {
return true;
}
public function getRoutes() {
return array(
'/M(?P<id>[1-9]\d*)' => 'PholioMockViewController',
'/pholio/' => array(
'' => 'PholioMockListController',
'view/(?P<view>\w+)/' => 'PholioMockListController',
'new/' => 'PholioMockEditController',
'edit/(?P<id>\d+)/' => 'PholioMockEditController',
'comment/(?P<id>\d+)/' => 'PholioMockCommentController',
+ 'inline/(?P<id>\d+)/' => 'PholioInlineSaveController',
),
);
}
}
diff --git a/src/applications/pholio/constants/PholioTransactionType.php b/src/applications/pholio/constants/PholioTransactionType.php
index f2227a0401..561e813b66 100644
--- a/src/applications/pholio/constants/PholioTransactionType.php
+++ b/src/applications/pholio/constants/PholioTransactionType.php
@@ -1,8 +1,9 @@
<?php
final class PholioTransactionType extends PholioConstants {
const TYPE_NAME = 'name';
const TYPE_DESCRIPTION = 'description';
+ const TYPE_INLINE = 'inline';
}
diff --git a/src/applications/pholio/controller/PholioInlineSaveController.php b/src/applications/pholio/controller/PholioInlineSaveController.php
new file mode 100644
index 0000000000..5db75f6931
--- /dev/null
+++ b/src/applications/pholio/controller/PholioInlineSaveController.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * @group pholio
+ */
+final class PholioInlineSaveController extends PholioController {
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $user = $request->getUser();
+
+ $mock = id(new PholioMockQuery())
+ ->setViewer($user)
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->withIDs(array($request->getInt('mockID')))
+ ->executeOne();
+
+ if (!$mock) {
+ return new Aphront404Response();
+ }
+
+ $draft = id(new PholioTransactionComment());
+ $draft->setImageID($request->getInt('imageID'));
+ $draft->setX($request->getInt('startX'));
+ $draft->setY($request->getInt('startY'));
+
+ $draft->setCommentVersion(1);
+ $draft->setAuthorPHID($user->getPHID());
+ $draft->setEditPolicy($user->getPHID());
+ $draft->setViewPolicy(PhabricatorPolicies::POLICY_PUBLIC);
+
+ $content_source = PhabricatorContentSource::newForSource(
+ PhabricatorContentSource::SOURCE_WEB,
+ array(
+ 'ip' => $request->getRemoteAddr(),
+ ));
+
+ $draft->setContentSource($content_source);
+
+ $draft->setWidth($request->getInt('endX') - $request->getInt('startX'));
+ $draft->setHeight($request->getInt('endY') - $request->getInt('startY'));
+
+ $draft->setContent($request->getStr('comment'));
+
+ $draft->save();
+
+ return id(new AphrontAjaxResponse())->setContent(array());
+ }
+
+}
diff --git a/src/applications/pholio/controller/PholioMockCommentController.php b/src/applications/pholio/controller/PholioMockCommentController.php
index 51ade41e94..2830adeec8 100644
--- a/src/applications/pholio/controller/PholioMockCommentController.php
+++ b/src/applications/pholio/controller/PholioMockCommentController.php
@@ -1,81 +1,94 @@
<?php
/**
* @group pholio
*/
final class PholioMockCommentController extends PholioController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
if (!$request->isFormPost()) {
return new Aphront400Response();
}
$mock = id(new PholioMockQuery())
->setViewer($user)
->withIDs(array($this->id))
+ ->needImages(true)
->executeOne();
if (!$mock) {
return new Aphront404Response();
}
$is_preview = $request->isPreviewRequest();
$draft = PhabricatorDraft::buildFromRequest($request);
$mock_uri = '/M'.$mock->getID();
$comment = $request->getStr('comment');
$content_source = PhabricatorContentSource::newForSource(
PhabricatorContentSource::SOURCE_WEB,
array(
'ip' => $request->getRemoteAddr(),
));
$xactions = array();
$xactions[] = id(new PholioTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new PholioTransactionComment())
->setContent($comment));
+ $inlineComments = id(new PholioTransactionComment())->loadAllWhere(
+ 'authorphid = %s AND transactionphid IS NULL AND imageid IN (%Ld)',
+ $user->getPHID(),
+ mpull($mock->getImages(), 'getID')
+ );
+
+ foreach ($inlineComments as $inlineComment) {
+ $xactions[] = id(new PholioTransaction())
+ ->setTransactionType(PholioTransactionType::TYPE_INLINE)
+ ->attachComment($inlineComment);
+ }
+
$editor = id(new PholioMockEditor())
->setActor($user)
->setContentSource($content_source)
->setContinueOnNoEffect($request->isContinueRequest())
->setIsPreview($is_preview);
try {
$xactions = $editor->applyTransactions($mock, $xactions);
} catch (PhabricatorApplicationTransactionNoEffectException $ex) {
return id(new PhabricatorApplicationTransactionNoEffectResponse())
->setCancelURI($mock_uri)
->setException($ex);
}
if ($draft) {
$draft->replaceOrDelete();
}
if ($request->isAjax()) {
return id(new PhabricatorApplicationTransactionResponse())
->setViewer($user)
->setTransactions($xactions)
->setIsPreview($is_preview)
->setAnchorOffset($request->getStr('anchor'));
} else {
return id(new AphrontRedirectResponse())->setURI($mock_uri);
}
}
}
diff --git a/src/applications/pholio/editor/PholioMockEditor.php b/src/applications/pholio/editor/PholioMockEditor.php
index 36ab5a847a..51502bb593 100644
--- a/src/applications/pholio/editor/PholioMockEditor.php
+++ b/src/applications/pholio/editor/PholioMockEditor.php
@@ -1,130 +1,143 @@
<?php
/**
* @group pholio
*/
final class PholioMockEditor extends PhabricatorApplicationTransactionEditor {
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = PhabricatorTransactions::TYPE_COMMENT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
$types[] = PholioTransactionType::TYPE_NAME;
$types[] = PholioTransactionType::TYPE_DESCRIPTION;
+ $types[] = PholioTransactionType::TYPE_INLINE;
return $types;
}
protected function getCustomTransactionOldValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PholioTransactionType::TYPE_NAME:
return $object->getName();
case PholioTransactionType::TYPE_DESCRIPTION:
return $object->getDescription();
}
}
protected function getCustomTransactionNewValue(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PholioTransactionType::TYPE_NAME:
case PholioTransactionType::TYPE_DESCRIPTION:
return $xaction->getNewValue();
}
}
+ protected function transactionHasEffect(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PholioTransactionType::TYPE_INLINE:
+ return true;
+ }
+
+ return parent::transactionHasEffect($object, $xaction);
+ }
+
protected function applyCustomInternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PholioTransactionType::TYPE_NAME:
$object->setName($xaction->getNewValue());
if ($object->getOriginalName() === null) {
$object->setOriginalName($xaction->getNewValue());
}
break;
case PholioTransactionType::TYPE_DESCRIPTION:
$object->setDescription($xaction->getNewValue());
break;
}
}
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
return;
}
protected function mergeTransactions(
PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) {
$type = $u->getTransactionType();
switch ($type) {
case PholioTransactionType::TYPE_NAME:
case PholioTransactionType::TYPE_DESCRIPTION:
return $v;
}
return parent::mergeTransactions($u, $v);
}
protected function supportsMail() {
return true;
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new PholioReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$name = $object->getName();
$original_name = $object->getOriginalName();
return id(new PhabricatorMetaMTAMail())
->setSubject("M{$id}: {$name}")
->addHeader('Thread-Topic', "M{$id}: {$original_name}");
}
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
$object->getAuthorPHID(),
$this->requireActor()->getPHID(),
);
}
protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
$body = parent::buildMailBody($object, $xactions);
$body->addTextSection(
pht('MOCK DETAIL'),
PhabricatorEnv::getProductionURI('/M'.$object->getID()));
return $body;
}
protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.pholio.subject-prefix');
}
protected function supportsFeed() {
return true;
}
protected function supportsSearch() {
return true;
}
}
diff --git a/src/applications/pholio/view/PholioMockImagesView.php b/src/applications/pholio/view/PholioMockImagesView.php
index b8517dc82c..71d8615c8c 100644
--- a/src/applications/pholio/view/PholioMockImagesView.php
+++ b/src/applications/pholio/view/PholioMockImagesView.php
@@ -1,84 +1,86 @@
<?php
final class PholioMockImagesView extends AphrontView {
private $mock;
public function setMock(PholioMock $mock) {
$this->mock = $mock;
}
public function render() {
if (!$this->mock) {
throw new Exception("Call setMock() before render()!");
}
$main_image_id = celerity_generate_unique_node_id();
require_celerity_resource('javelin-behavior-pholio-mock-view');
- $config = array('mainID' => $main_image_id);
+ $config = array(
+ 'mainID' => $main_image_id,
+ 'mockID' => $this->mock->getID());
Javelin::initBehavior('pholio-mock-view', $config);
$mockview = "";
$main_image = head($this->mock->getImages());
$main_image_tag = javelin_tag(
'img',
array(
'id' => $main_image_id,
'src' => $main_image->getFile()->getBestURI(),
'sigil' => 'mock-image',
'class' => 'pholio-mock-image',
'meta' => array(
'fullSizeURI' => $main_image->getFile()->getBestURI(),
'imageID' => $main_image->getID(),
),
));
$main_image_tag = javelin_tag(
'div',
array(
'id' => 'mock-wrapper',
'sigil' => 'mock-wrapper',
'class' => 'pholio-mock-wrapper'
),
$main_image_tag
);
$mockview[] = phutil_tag(
'div',
array(
'class' => 'pholio-mock-image-container',
),
$main_image_tag);
if (count($this->mock->getImages()) > 1) {
$thumbnails = array();
foreach ($this->mock->getImages() as $image) {
$thumbfile = $image->getFile();
$tag = javelin_tag(
'img',
array(
'src' => $thumbfile->getThumb160x120URI(),
'sigil' => 'mock-thumbnail',
'class' => 'pholio-mock-carousel-thumbnail',
'meta' => array(
'fullSizeURI' => $thumbfile->getBestURI(),
'imageID' => $image->getID()
),
));
$thumbnails[] = $tag;
}
$mockview[] = phutil_tag(
'div',
array(
'class' => 'pholio-mock-carousel',
),
$thumbnails);
}
return $this->renderHTMLView($mockview);
}
}
diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php
index fe0680a121..fc35653e6b 100644
--- a/src/applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php
+++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php
@@ -1,102 +1,105 @@
<?php
final class PhabricatorApplicationTransactionCommentEditor
extends PhabricatorEditor {
private $contentSource;
public function setContentSource(PhabricatorContentSource $content_source) {
$this->contentSource = $content_source;
return $this;
}
public function getContentSource() {
return $this->contentSource;
}
/**
* Edit a transaction's comment. This method effects the required create,
* update or delete to set the transaction's comment to the provided comment.
*/
public function applyEdit(
PhabricatorApplicationTransaction $xaction,
PhabricatorApplicationTransactionComment $comment) {
$this->validateEdit($xaction, $comment);
$actor = $this->requireActor();
$comment->setContentSource($this->getContentSource());
$comment->setAuthorPHID($actor->getPHID());
// TODO: This needs to be more sophisticated once we have meta-policies.
$comment->setViewPolicy(PhabricatorPolicies::POLICY_PUBLIC);
$comment->setEditPolicy($actor->getPHID());
$xaction->openTransaction();
$xaction->beginReadLocking();
if ($xaction->getID()) {
$xaction->reload();
}
$new_version = $xaction->getCommentVersion() + 1;
$comment->setCommentVersion($new_version);
$comment->setTransactionPHID($xaction->getPHID());
$comment->save();
$xaction->setCommentVersion($new_version);
$xaction->setCommentPHID($comment->getPHID());
$xaction->setViewPolicy($comment->getViewPolicy());
$xaction->setEditPolicy($comment->getEditPolicy());
$xaction->save();
$xaction->endReadLocking();
$xaction->saveTransaction();
$xaction->attachComment($comment);
// TODO: Emit an event for notifications/feed? Can we handle them
// generically?
return $this;
}
/**
* Validate that the edit is permissible, and the actor has permission to
* perform it.
*/
private function validateEdit(
PhabricatorApplicationTransaction $xaction,
PhabricatorApplicationTransactionComment $comment) {
if (!$xaction->getPHID()) {
throw new Exception(
"Transaction must have a PHID before calling applyEdit()!");
}
- if ($comment->getPHID()) {
- throw new Exception(
+ $type_comment = PhabricatorTransactions::TYPE_COMMENT;
+ if ($xaction->getTransactionType() == $type_comment) {
+ if ($comment->getPHID()) {
+ throw new Exception(
"Transaction comment must not yet have a PHID!");
+ }
}
if (!$this->getContentSource()) {
throw new Exception(
"Call setContentSource() before applyEdit()!");
}
$actor = $this->requireActor();
PhabricatorPolicyFilter::requireCapability(
$actor,
$xaction,
PhabricatorPolicyCapability::CAN_VIEW);
PhabricatorPolicyFilter::requireCapability(
$actor,
$xaction,
PhabricatorPolicyCapability::CAN_EDIT);
}
}
diff --git a/src/infrastructure/daemon/bot/PhabricatorBot.php b/src/infrastructure/daemon/bot/PhabricatorBot.php
new file mode 100644
index 0000000000..1159726acb
--- /dev/null
+++ b/src/infrastructure/daemon/bot/PhabricatorBot.php
@@ -0,0 +1,132 @@
+<?php
+
+/**
+ * Simple IRC bot which runs as a Phabricator daemon. Although this bot is
+ * somewhat useful, it is also intended to serve as a demo of how to write
+ * "system agents" which communicate with Phabricator over Conduit, so you can
+ * script system interactions and integrate with other systems.
+ *
+ * NOTE: This is super janky and experimental right now.
+ *
+ * @group irc
+ */
+final class PhabricatorBot extends PhabricatorDaemon {
+
+ private $handlers;
+
+ private $conduit;
+ private $config;
+ private $pollFrequency;
+
+ public function run() {
+ $argv = $this->getArgv();
+ if (count($argv) !== 1) {
+ throw new Exception("usage: PhabricatorBot <json_config_file>");
+ }
+
+ $json_raw = Filesystem::readFile($argv[0]);
+ $config = json_decode($json_raw, true);
+ if (!is_array($config)) {
+ throw new Exception("File '{$argv[0]}' is not valid JSON!");
+ }
+
+ $nick = idx($config, 'nick', 'phabot');
+ $handlers = idx($config, 'handlers', array());
+ $protocol_adapter_class = idx(
+ $config,
+ 'protocol-adapter',
+ 'PhabricatorIRCProtocolAdapter');
+ $this->pollFrequency = idx($config, 'poll-frequency', 1);
+
+ $this->config = $config;
+
+ foreach ($handlers as $handler) {
+ $obj = newv($handler, array($this));
+ $this->handlers[] = $obj;
+ }
+
+ $conduit_uri = idx($config, 'conduit.uri');
+ if ($conduit_uri) {
+ $conduit_user = idx($config, 'conduit.user');
+ $conduit_cert = idx($config, 'conduit.cert');
+
+ // Normalize the path component of the URI so users can enter the
+ // domain without the "/api/" part.
+ $conduit_uri = new PhutilURI($conduit_uri);
+ $conduit_uri->setPath('/api/');
+ $conduit_uri = (string)$conduit_uri;
+
+ $conduit = new ConduitClient($conduit_uri);
+ $response = $conduit->callMethodSynchronous(
+ 'conduit.connect',
+ array(
+ 'client' => 'PhabricatorBot',
+ 'clientVersion' => '1.0',
+ 'clientDescription' => php_uname('n').':'.$nick,
+ 'user' => $conduit_user,
+ 'certificate' => $conduit_cert,
+ ));
+
+ $this->conduit = $conduit;
+ }
+
+ // Instantiate Protocol Adapter, for now follow same technique as
+ // handler instantiation
+ $this->protocolAdapter = newv($protocol_adapter_class, array());
+ $this->protocolAdapter
+ ->setConfig($this->config)
+ ->connect();
+
+ $this->runLoop();
+ }
+
+ public function getConfig($key, $default = null) {
+ return idx($this->config, $key, $default);
+ }
+
+ private function runLoop() {
+ do {
+ $this->stillWorking();
+
+ $messages = $this->protocolAdapter->getNextMessages($this->pollFrequency);
+ if (count($messages) > 0) {
+ foreach ($messages as $message) {
+ $this->routeMessage($message);
+ }
+ }
+
+ foreach ($this->handlers as $handler) {
+ $handler->runBackgroundTasks();
+ }
+ } while (true);
+ }
+
+ public function writeMessage(PhabricatorBotMessage $message) {
+ return $this->protocolAdapter->writeMessage($message);
+ }
+
+ private function routeMessage(PhabricatorBotMessage $message) {
+ $ignore = $this->getConfig('ignore');
+ if ($ignore && in_array($message->getSenderNickName(), $ignore)) {
+ return;
+ }
+
+ foreach ($this->handlers as $handler) {
+ try {
+ $handler->receiveMessage($message);
+ } catch (Exception $ex) {
+ phlog($ex);
+ }
+ }
+ }
+
+ public function getConduit() {
+ if (empty($this->conduit)) {
+ throw new Exception(
+ "This bot is not configured with a Conduit uplink. Set 'conduit.uri', ".
+ "'conduit.user' and 'conduit.cert' in the configuration to connect.");
+ }
+ return $this->conduit;
+ }
+
+}
diff --git a/src/infrastructure/daemon/bot/PhabricatorBotMessage.php b/src/infrastructure/daemon/bot/PhabricatorBotMessage.php
new file mode 100644
index 0000000000..c3c03748f1
--- /dev/null
+++ b/src/infrastructure/daemon/bot/PhabricatorBotMessage.php
@@ -0,0 +1,68 @@
+<?php
+
+final class PhabricatorBotMessage {
+
+ private $sender;
+ private $command;
+ private $body;
+ private $target;
+ private $public;
+
+ public function __construct() {
+ // By default messages are public
+ $this->public = true;
+ }
+
+ public function setSender($sender) {
+ $this->sender = $sender;
+ return $this;
+ }
+
+ public function getSender() {
+ return $this->sender;
+ }
+
+ public function setCommand($command) {
+ $this->command = $command;
+ return $this;
+ }
+
+ public function getCommand() {
+ return $this->command;
+ }
+
+ public function setBody($body) {
+ $this->body = $body;
+ return $this;
+ }
+
+ public function getBody() {
+ return $this->body;
+ }
+
+ public function setTarget($target) {
+ $this->target = $target;
+ return $this;
+ }
+
+ public function getTarget() {
+ return $this->target;
+ }
+
+ public function isPublic() {
+ return $this->public;
+ }
+
+ public function setPublic($is_public) {
+ $this->public = $is_public;
+ return $this;
+ }
+
+ public function getReplyTo() {
+ if ($this->public) {
+ return $this->target;
+ } else {
+ return $this->sender;
+ }
+ }
+}
diff --git a/src/infrastructure/daemon/bot/PhabricatorIRCBot.php b/src/infrastructure/daemon/bot/PhabricatorIRCBot.php
new file mode 100644
index 0000000000..81f6cc0fec
--- /dev/null
+++ b/src/infrastructure/daemon/bot/PhabricatorIRCBot.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * Placeholder to let people know that the bot has been renamed
+ */
+final class PhabricatorIRCBot extends PhabricatorDaemon {
+ public function run() {
+ throw new Exception(
+ "This daemon has been deprecated, use `PhabricatorBot` instead.");
+ }
+}
diff --git a/src/infrastructure/daemon/bot/adapter/PhabricatorBaseProtocolAdapter.php b/src/infrastructure/daemon/bot/adapter/PhabricatorBaseProtocolAdapter.php
new file mode 100644
index 0000000000..55cb90ebd1
--- /dev/null
+++ b/src/infrastructure/daemon/bot/adapter/PhabricatorBaseProtocolAdapter.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * Defines the api for protocol adapters for @{class:PhabricatorBot}
+ */
+abstract class PhabricatorBaseProtocolAdapter {
+ protected $config;
+
+ public function setConfig($config) {
+ $this->config = $config;
+ return $this;
+ }
+
+ /**
+ * Performs any connection logic necessary for the protocol
+ */
+ abstract public function connect();
+
+ /**
+ * This is the spout for messages coming in from the protocol.
+ * This will be called in the main event loop of the bot daemon
+ * So if if doesn't implement some sort of blocking timeout
+ * (e.g. select-based socket polling), it should at least sleep
+ * for some period of time in order to not overwhelm the processor.
+ *
+ * @param Int $poll_frequency The number of seconds between polls
+ */
+ abstract public function getNextMessages($poll_frequency);
+
+ /**
+ * This is the output mechanism for the protocol.
+ *
+ * @param PhabricatorBotMessage $message The message to write
+ */
+ abstract public function writeMessage(PhabricatorBotMessage $message);
+}
diff --git a/src/infrastructure/daemon/bot/adapter/PhabricatorCampfireProtocolAdapter.php b/src/infrastructure/daemon/bot/adapter/PhabricatorCampfireProtocolAdapter.php
new file mode 100644
index 0000000000..59323baf6f
--- /dev/null
+++ b/src/infrastructure/daemon/bot/adapter/PhabricatorCampfireProtocolAdapter.php
@@ -0,0 +1,201 @@
+<?php
+
+final class PhabricatorCampfireProtocolAdapter
+extends PhabricatorBaseProtocolAdapter {
+
+ private $readBuffers;
+ private $authtoken;
+ private $server;
+ private $readHandles;
+ private $multiHandle;
+ private $active;
+ private $rooms;
+
+ public function connect() {
+ $this->server = idx($this->config, 'server');
+ $this->authtoken = idx($this->config, 'authtoken');
+ $ssl = idx($this->config, 'ssl', false);
+ $this->rooms = idx($this->config, 'join');
+
+ // First, join the room
+ if (!$this->rooms) {
+ throw new Exception("Not configured to join any rooms!");
+ }
+
+ $this->readBuffers = array();
+
+ // Set up our long poll in a curl multi request so we can
+ // continue running while it executes in the background
+ $this->multiHandle = curl_multi_init();
+ $this->readHandles = array();
+
+ foreach ($this->rooms as $room_id) {
+ $this->joinRoom($room_id);
+
+ // Set up the curl stream for reading
+ $url = ($ssl) ? "https://" : "http://";
+ $url .= "streaming.campfirenow.com/room/{$room_id}/live.json";
+ $this->readHandle[$url] = curl_init();
+ curl_setopt($this->readHandle[$url], CURLOPT_URL, $url);
+ curl_setopt($this->readHandle[$url], CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($this->readHandle[$url], CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt(
+ $this->readHandle[$url],
+ CURLOPT_USERPWD,
+ $this->authtoken.':x');
+ curl_setopt(
+ $this->readHandle[$url],
+ CURLOPT_HTTPHEADER,
+ array("Content-type: application/json"));
+ curl_setopt(
+ $this->readHandle[$url],
+ CURLOPT_WRITEFUNCTION,
+ array($this, 'read'));
+ curl_setopt($this->readHandle[$url], CURLOPT_BUFFERSIZE, 128);
+ curl_setopt($this->readHandle[$url], CURLOPT_TIMEOUT, 0);
+
+ curl_multi_add_handle($this->multiHandle, $this->readHandle[$url]);
+
+ // Initialize read buffer
+ $this->readBuffers[$url] = '';
+ }
+
+ $this->active = null;
+ $this->blockingMultiExec();
+ }
+
+ // This is our callback for the background curl multi-request.
+ // Puts the data read in on the readBuffer for processing.
+ private function read($ch, $data) {
+ $info = curl_getinfo($ch);
+ $length = strlen($data);
+ $this->readBuffers[$info['url']] .= $data;
+ return $length;
+ }
+
+ private function blockingMultiExec() {
+ do {
+ $status = curl_multi_exec($this->multiHandle, $this->active);
+ } while ($status == CURLM_CALL_MULTI_PERFORM);
+
+ // Check for errors
+ if ($status != CURLM_OK) {
+ throw new Exception(
+ "Phabricator Bot had a problem reading from campfire.");
+ }
+ }
+
+ public function getNextMessages($poll_frequency) {
+ $messages = array();
+
+ if (!$this->active) {
+ throw new Exception("Phabricator Bot stopped reading from campfire.");
+ }
+
+ // Prod our http request
+ curl_multi_select($this->multiHandle, $poll_frequency);
+ $this->blockingMultiExec();
+
+ // Process anything waiting on the read buffer
+ while ($m = $this->processReadBuffer()) {
+ $messages[] = $m;
+ }
+
+ return $messages;
+ }
+
+ private function processReadBuffer() {
+ foreach ($this->readBuffers as $url => &$buffer) {
+ $until = strpos($buffer, "}\r");
+ if ($until == false) {
+ continue;
+ }
+
+ $message = substr($buffer, 0, $until + 1);
+ $buffer = substr($buffer, $until + 2);
+
+ $m_obj = json_decode($message, true);
+
+ return id(new PhabricatorBotMessage())
+ ->setCommand('MESSAGE')
+ ->setTarget($m_obj['room_id'])
+ ->setBody($m_obj['body']);
+ }
+
+ // If we're here, there's nothing to process
+ return false;
+ }
+
+ public function writeMessage(PhabricatorBotMessage $message) {
+ switch ($message->getCommand()) {
+ case 'MESSAGE':
+ $this->speak(
+ $message->getBody(),
+ $message->getTarget());
+ break;
+ }
+ }
+
+ private function joinRoom($room_id) {
+ $this->performPost("/room/{$room_id}/join.json");
+ }
+
+ private function leaveRoom($room_id) {
+ $this->performPost("/room/{$room_id}/leave.json");
+ }
+
+ private function speak($message, $room_id) {
+ $this->performPost(
+ "/room/{$room_id}/speak.json",
+ array(
+ 'message' => array(
+ 'type' => 'TextMessage',
+ 'body' => $message)));
+ }
+
+ private function performPost($endpoint, $data = Null) {
+ $url = $this->server.$endpoint;
+
+ $payload = json_encode($data);
+
+ // cURL init & config
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($ch, CURLOPT_USERPWD, $this->authtoken . ':x');
+ curl_setopt(
+ $ch,
+ CURLOPT_HTTPHEADER,
+ array("Content-type: application/json"));
+
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
+ $output = curl_exec($ch);
+
+ curl_close($ch);
+
+ $output = trim($output);
+
+ if (strlen($output)) {
+ return json_decode($output);
+ }
+
+ return true;
+ }
+
+ public function __destruct() {
+ if ($this->rooms) {
+ foreach ($this->rooms as $room_id) {
+ $this->leaveRoom($room_id);
+ }
+ }
+ if ($this->readHandles) {
+ foreach ($this->readHandles as $read_handle) {
+ curl_multi_remove_handle($this->multiHandle, $read_handle);
+ curl_close($read_handle);
+ }
+ }
+ curl_multi_close($this->multiHandle);
+ }
+}
diff --git a/src/infrastructure/daemon/bot/adapter/PhabricatorIRCProtocolAdapter.php b/src/infrastructure/daemon/bot/adapter/PhabricatorIRCProtocolAdapter.php
new file mode 100644
index 0000000000..f2d34db246
--- /dev/null
+++ b/src/infrastructure/daemon/bot/adapter/PhabricatorIRCProtocolAdapter.php
@@ -0,0 +1,221 @@
+<?php
+
+final class PhabricatorIRCProtocolAdapter
+extends PhabricatorBaseProtocolAdapter {
+
+ private $socket;
+
+ private $writeBuffer;
+ private $readBuffer;
+
+ // Hash map of command translations
+ public static $commandTranslations = array(
+ 'PRIVMSG' => 'MESSAGE');
+
+ public function connect() {
+ $nick = idx($this->config, 'nick', 'phabot');
+ $server = idx($this->config, 'server');
+ $port = idx($this->config, 'port', 6667);
+ $pass = idx($this->config, 'pass');
+ $ssl = idx($this->config, 'ssl', false);
+ $user = idx($this->config, 'user', $nick);
+
+ if (!preg_match('/^[A-Za-z0-9_`[{}^|\]\\-]+$/', $nick)) {
+ throw new Exception(
+ "Nickname '{$nick}' is invalid!");
+ }
+
+ $errno = null;
+ $error = null;
+ if (!$ssl) {
+ $socket = fsockopen($server, $port, $errno, $error);
+ } else {
+ $socket = fsockopen('ssl://'.$server, $port, $errno, $error);
+ }
+ if (!$socket) {
+ throw new Exception("Failed to connect, #{$errno}: {$error}");
+ }
+ $ok = stream_set_blocking($socket, false);
+ if (!$ok) {
+ throw new Exception("Failed to set stream nonblocking.");
+ }
+
+ $this->socket = $socket;
+ $this->writeMessage(
+ id(new PhabricatorBotMessage())
+ ->setCommand('USER')
+ ->setBody("{$user} 0 * :{$user}"));
+ if ($pass) {
+ $this->writeMessage(
+ id(new PhabricatorBotMessage())
+ ->setCommand('PASS')
+ ->setBody("{$pass}"));
+ }
+
+ $this->writeMessage(
+ id(new PhabricatorBotMessage())
+ ->setCommand('NICK')
+ ->setBody("{$nick}"));
+ }
+
+ public function getNextMessages($poll_frequency) {
+ $messages = array();
+
+ $read = array($this->socket);
+ if (strlen($this->writeBuffer)) {
+ $write = array($this->socket);
+ } else {
+ $write = array();
+ }
+ $except = array();
+
+ $ok = @stream_select($read, $write, $except, $timeout_sec = 1);
+ if ($ok === false) {
+ throw new Exception(
+ "socket_select() failed: ".socket_strerror(socket_last_error()));
+ }
+
+ if ($read) {
+ // Test for connection termination; in PHP, fread() off a nonblocking,
+ // closed socket is empty string.
+ if (feof($this->socket)) {
+ // This indicates the connection was terminated on the other side,
+ // just exit via exception and let the overseer restart us after a
+ // delay so we can reconnect.
+ throw new Exception("Remote host closed connection.");
+ }
+ do {
+ $data = fread($this->socket, 4096);
+ if ($data === false) {
+ throw new Exception("fread() failed!");
+ } else {
+ $messages[] = id(new PhabricatorBotMessage())
+ ->setCommand("LOG")
+ ->setBody(">>> ".$data);
+ $this->readBuffer .= $data;
+ }
+ } while (strlen($data));
+ }
+
+ if ($write) {
+ do {
+ $len = fwrite($this->socket, $this->writeBuffer);
+ if ($len === false) {
+ throw new Exception("fwrite() failed!");
+ } else {
+ $messages[] = id(new PhabricatorBotMessage())
+ ->setCommand("LOG")
+ ->setBody(">>> ".substr($this->writeBuffer, 0, $len));
+ $this->writeBuffer = substr($this->writeBuffer, $len);
+ }
+ } while (strlen($this->writeBuffer));
+ }
+
+ while ($m = $this->processReadBuffer()) {
+ $messages[] = $m;
+ }
+
+ return $messages;
+ }
+
+ private function write($message) {
+ $this->writeBuffer .= $message;
+ return $this;
+ }
+
+ public function writeMessage(PhabricatorBotMessage $message) {
+ $irc_command = $this->getIRCCommand($message->getCommand());
+ switch ($message->getCommand()) {
+ case 'MESSAGE':
+ $data = $irc_command.' '.
+ $message->getTarget().' :'.
+ $message->getBody()."\r\n";
+ break;
+ default:
+ $data = $irc_command.' '.
+ $message->getBody()."\r\n";
+ break;
+ }
+
+ return $this->write($data);
+ }
+
+ private function processReadBuffer() {
+ $until = strpos($this->readBuffer, "\r\n");
+ if ($until === false) {
+ return false;
+ }
+
+ $message = substr($this->readBuffer, 0, $until);
+ $this->readBuffer = substr($this->readBuffer, $until + 2);
+
+ $pattern =
+ '/^'.
+ '(?::(?P<sender>(\S+?))(?:!\S*)? )?'. // This may not be present.
+ '(?P<command>[A-Z0-9]+) '.
+ '(?P<data>.*)'.
+ '$/';
+
+ $matches = null;
+ if (!preg_match($pattern, $message, $matches)) {
+ throw new Exception("Unexpected message from server: {$message}");
+ }
+
+ $command = $this->getBotCommand($matches['command']);
+ list($target, $body) = $this->parseMessageData($command, $matches['data']);
+
+ $bot_message = id(new PhabricatorBotMessage())
+ ->setSender(idx($matches, 'sender'))
+ ->setCommand($command)
+ ->setTarget($target)
+ ->setBody($body);
+
+ if (!empty($target) && strncmp($target, '#', 1) !== 0) {
+ $bot_message->setPublic(false);
+ }
+
+ return $bot_message;
+ }
+
+ private function getBotCommand($irc_command) {
+ if (isset(self::$commandTranslations[$irc_command])) {
+ return self::$commandTranslations[$irc_command];
+ }
+
+ // We have no translation for this command, use as-is
+ return $irc_command;
+ }
+
+ private function getIRCCommand($original_bot_command) {
+ foreach (self::$commandTranslations as $irc_command=>$bot_command) {
+ if ($bot_command === $original_bot_command) {
+ return $irc_command;
+ }
+ }
+
+ return $original_bot_command;
+ }
+
+ private function parseMessageData($command, $data) {
+ switch ($command) {
+ case 'MESSAGE':
+ $matches = null;
+ if (preg_match('/^(\S+)\s+:?(.*)$/', $data, $matches)) {
+ return array(
+ $matches[1],
+ rtrim($matches[2], "\r\n"));
+ }
+ break;
+ }
+
+ // By default we assume there is no target, only a body
+ return array(
+ null,
+ $data);
+ }
+
+ public function __destruct() {
+ $this->write("QUIT Goodbye.\r\n");
+ fclose($this->socket);
+ }
+}
diff --git a/src/infrastructure/daemon/bot/handler/PhabricatorBotDebugLogHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotDebugLogHandler.php
new file mode 100644
index 0000000000..7c2d0b57cb
--- /dev/null
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotDebugLogHandler.php
@@ -0,0 +1,17 @@
+<?php
+
+/**
+ * Logs messages to stdout
+ */
+final class PhabricatorBotDebugLogHandler extends PhabricatorBotHandler {
+ public function receiveMessage(PhabricatorBotMessage $message) {
+ switch ($message->getCommand()) {
+ case 'LOG':
+ echo addcslashes(
+ $message->getBody(),
+ "\0..\37\177..\377");
+ echo "\n";
+ break;
+ }
+ }
+}
diff --git a/src/infrastructure/daemon/irc/handler/PhabricatorIRCDifferentialNotificationHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotDifferentialNotificationHandler.php
similarity index 74%
rename from src/infrastructure/daemon/irc/handler/PhabricatorIRCDifferentialNotificationHandler.php
rename to src/infrastructure/daemon/bot/handler/PhabricatorBotDifferentialNotificationHandler.php
index c0a1f9fc88..3a252cfc5e 100644
--- a/src/infrastructure/daemon/irc/handler/PhabricatorIRCDifferentialNotificationHandler.php
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotDifferentialNotificationHandler.php
@@ -1,51 +1,56 @@
<?php
/**
* @group irc
*/
-final class PhabricatorIRCDifferentialNotificationHandler
- extends PhabricatorIRCHandler {
+final class PhabricatorBotDifferentialNotificationHandler
+extends PhabricatorBotHandler {
private $skippedOldEvents;
- public function receiveMessage(PhabricatorIRCMessage $message) {
+ public function receiveMessage(PhabricatorBotMessage $message) {
return;
}
public function runBackgroundTasks() {
$iterator = new PhabricatorTimelineIterator('ircdiffx', array('difx'));
$show = $this->getConfig('notification.actions');
if (!$this->skippedOldEvents) {
// Since we only want to post notifications about new events, skip
// everything that's happened in the past when we start up so we'll
// only process real-time events.
foreach ($iterator as $event) {
// Ignore all old events.
}
$this->skippedOldEvents = true;
return;
}
foreach ($iterator as $event) {
$data = $event->getData();
if (!$data || ($show !== null && !in_array($data['action'], $show))) {
continue;
}
$actor_phid = $data['actor_phid'];
$phids = array($actor_phid);
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$verb = DifferentialAction::getActionPastTenseVerb($data['action']);
$actor_name = $handles[$actor_phid]->getName();
- $message = "{$actor_name} {$verb} revision D".$data['revision_id'].".";
+ $message_body =
+ "{$actor_name} {$verb} revision D".$data['revision_id'].".";
$channels = $this->getConfig('notification.channels', array());
foreach ($channels as $channel) {
- $this->write('PRIVMSG', "{$channel} :{$message}");
+ $this->writeMessage(
+ id(new PhabricatorBotMessage())
+ ->setCommand('MESSAGE')
+ ->setTarget($channel)
+ ->setBody($message_body));
}
}
}
}
diff --git a/src/infrastructure/daemon/irc/handler/PhabricatorIRCFeedNotificationHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotFeedNotificationHandler.php
similarity index 92%
rename from src/infrastructure/daemon/irc/handler/PhabricatorIRCFeedNotificationHandler.php
rename to src/infrastructure/daemon/bot/handler/PhabricatorBotFeedNotificationHandler.php
index 6f45ed936f..abec6a5664 100644
--- a/src/infrastructure/daemon/irc/handler/PhabricatorIRCFeedNotificationHandler.php
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotFeedNotificationHandler.php
@@ -1,159 +1,163 @@
<?php
/**
* Watches the feed and puts notifications into channel(s) of choice
*
* @group irc
*/
-final class PhabricatorIRCFeedNotificationHandler
- extends PhabricatorIRCHandler {
+final class PhabricatorBotFeedNotificationHandler
+ extends PhabricatorBotHandler {
private $startupDelay = 30;
private $lastSeenChronoKey = 0;
private function shouldShowStory($story) {
$story_class = $story['class'];
$story_text = $story['text'];
$show = $this->getConfig('notification.types');
if ($show) {
$obj_type = str_replace('PhabricatorFeedStory', '', $story_class);
if (!in_array(strtolower($obj_type), $show)) {
return false;
}
}
$verbosity = $this->getConfig('notification.verbosity', 3);
$verbs = array();
switch ($verbosity) {
case 2:
$verbs[] = array(
'commented',
'added',
'changed',
'resigned',
'explained',
'modified',
'attached',
'edited',
'joined',
'left',
'removed'
);
// fallthrough
case 1:
$verbs[] = array(
'updated',
'accepted',
'requested',
'planned',
'claimed',
'summarized',
'commandeered',
'assigned'
);
// fallthrough
case 0:
$verbs[] = array(
'created',
'closed',
'raised',
'committed',
'reopened',
'deleted'
);
break;
case 3:
default:
return true;
break;
}
$verbs = '/('.implode('|', array_mergev($verbs)).')/';
if (preg_match($verbs, $story_text)) {
return true;
}
return false;
}
- public function receiveMessage(PhabricatorIRCMessage $message) {
+ public function receiveMessage(PhabricatorBotMessage $message) {
return;
}
public function runBackgroundTasks() {
if ($this->startupDelay > 0) {
// the event loop runs every 1s so delay enough to fully conenct
$this->startupDelay--;
return;
}
if ($this->lastSeenChronoKey == 0) {
// Since we only want to post notifications about new stories, skip
// everything that's happened in the past when we start up so we'll
// only process real-time stories.
$latest = $this->getConduit()->callMethodSynchronous(
'feed.query',
array(
'limit'=>1
));
foreach ($latest as $story) {
if ($story['chronologicalKey'] > $this->lastSeenChronoKey) {
$this->lastSeenChronoKey = $story['chronologicalKey'];
}
}
return;
}
$config_max_pages = $this->getConfig('notification.max_pages', 5);
$config_page_size = $this->getConfig('notification.page_size', 10);
$last_seen_chrono_key = $this->lastSeenChronoKey;
$chrono_key_cursor = 0;
// Not efficient but works due to feed.query API
for ($max_pages = $config_max_pages; $max_pages > 0; $max_pages--) {
$stories = $this->getConduit()->callMethodSynchronous(
'feed.query',
array(
'limit'=>$config_page_size,
'after'=>$chrono_key_cursor,
'view'=>'text'
));
foreach ($stories as $story) {
if ($story['chronologicalKey'] == $last_seen_chrono_key) {
// Caught up on feed
return;
}
if ($story['chronologicalKey'] > $this->lastSeenChronoKey) {
// Keep track of newest seen story
$this->lastSeenChronoKey = $story['chronologicalKey'];
}
if (!$chrono_key_cursor ||
$story['chronologicalKey'] < $chrono_key_cursor) {
// Keep track of oldest story on this page
$chrono_key_cursor = $story['chronologicalKey'];
}
if (!$story['text'] ||
!$this->shouldShowStory($story)) {
continue;
}
$channels = $this->getConfig('join');
foreach ($channels as $channel) {
- $this->write('PRIVMSG', "{$channel} :{$story['text']}");
+ $this->writeMessage(
+ id(new PhabricatorBotMessage())
+ ->setCommand('MESSAGE')
+ ->setTarget($channel)
+ ->setBody($story['text']));
}
}
}
}
}
diff --git a/src/infrastructure/daemon/bot/handler/PhabricatorBotHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotHandler.php
new file mode 100644
index 0000000000..bf32d01cb6
--- /dev/null
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotHandler.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * Responds to IRC messages. You plug a bunch of these into a
+ * @{class:PhabricatorBot} to give it special behavior.
+ *
+ * @group irc
+ */
+abstract class PhabricatorBotHandler {
+
+ private $bot;
+
+ final public function __construct(PhabricatorBot $irc_bot) {
+ $this->bot = $irc_bot;
+ }
+
+ final protected function writeMessage(PhabricatorBotMessage $message) {
+ $this->bot->writeMessage($message);
+ return $this;
+ }
+
+ final protected function getConduit() {
+ return $this->bot->getConduit();
+ }
+
+ final protected function getConfig($key, $default = null) {
+ return $this->bot->getConfig($key, $default);
+ }
+
+ final protected function getURI($path) {
+ $base_uri = new PhutilURI($this->bot->getConfig('conduit.uri'));
+ $base_uri->setPath($path);
+ return (string)$base_uri;
+ }
+
+ abstract public function receiveMessage(PhabricatorBotMessage $message);
+
+ public function runBackgroundTasks() {
+ return;
+ }
+
+ public function replyTo($original_message, $body) {
+ if ($original_message->getCommand() != 'MESSAGE') {
+ throw new Exception(
+ "Handler is trying to reply to something which is not a message!");
+ }
+
+ $reply = id(new PhabricatorBotMessage())
+ ->setCommand('MESSAGE');
+
+ if ($original_message->isPublic()) {
+ // This is a public target, like a chatroom. Send the response to the
+ // chatroom.
+ $reply->setTarget($original_message->getTarget());
+ } else {
+ // This is a private target, like a private message. Send the response
+ // back to the sender (presumably, we are the target).
+ $reply->setTarget($original_message->getSender())
+ ->setPublic(false);
+ }
+
+ $reply->setBody($body);
+
+ return $this->writeMessage($reply);
+ }
+}
diff --git a/src/infrastructure/daemon/irc/handler/PhabricatorIRCLogHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotLogHandler.php
similarity index 76%
rename from src/infrastructure/daemon/irc/handler/PhabricatorIRCLogHandler.php
rename to src/infrastructure/daemon/bot/handler/PhabricatorBotLogHandler.php
index 5576aa8bb3..bc2962365e 100644
--- a/src/infrastructure/daemon/irc/handler/PhabricatorIRCLogHandler.php
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotLogHandler.php
@@ -1,78 +1,79 @@
<?php
/**
* Logs chatter.
*
* @group irc
*/
-final class PhabricatorIRCLogHandler extends PhabricatorIRCHandler {
+final class PhabricatorBotLogHandler extends PhabricatorBotHandler {
private $futures = array();
- public function receiveMessage(PhabricatorIRCMessage $message) {
+ public function receiveMessage(PhabricatorBotMessage $message) {
switch ($message->getCommand()) {
- case 'PRIVMSG':
+ case 'MESSAGE':
$reply_to = $message->getReplyTo();
if (!$reply_to) {
break;
}
- if (!$this->isChannelName($reply_to)) {
+ if (!$message->isPublic()) {
// Don't log private messages, although maybe we should for debugging?
break;
}
$logs = array(
array(
'channel' => $reply_to,
'type' => 'mesg',
'epoch' => time(),
- 'author' => $message->getSenderNickname(),
- 'message' => $message->getMessageText(),
+ 'author' => $message->getSender(),
+ 'message' => $message->getBody(),
),
);
$this->futures[] = $this->getConduit()->callMethod(
'chatlog.record',
array(
'logs' => $logs,
));
$prompts = array(
'/where is the (chat)?log\?/i',
'/where am i\?/i',
'/what year is (this|it)\?/i',
);
$tell = false;
foreach ($prompts as $prompt) {
- if (preg_match($prompt, $message->getMessageText())) {
+ if (preg_match($prompt, $message->getBody())) {
$tell = true;
break;
}
}
if ($tell) {
$response = $this->getURI(
'/chatlog/channel/'.phutil_escape_uri($reply_to).'/');
- $this->write('PRIVMSG', "{$reply_to} :{$response}");
+
+ $this->replyTo($message, $response);
}
break;
}
}
public function runBackgroundTasks() {
foreach ($this->futures as $key => $future) {
try {
if ($future->isReady()) {
unset($this->futures[$key]);
}
} catch (Exception $ex) {
unset($this->futures[$key]);
phlog($ex);
}
}
}
}
diff --git a/src/infrastructure/daemon/irc/handler/PhabricatorIRCMacroHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotMacroHandler.php
similarity index 73%
rename from src/infrastructure/daemon/irc/handler/PhabricatorIRCMacroHandler.php
rename to src/infrastructure/daemon/bot/handler/PhabricatorBotMacroHandler.php
index 078d77ac31..daa92424a0 100644
--- a/src/infrastructure/daemon/irc/handler/PhabricatorIRCMacroHandler.php
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotMacroHandler.php
@@ -1,187 +1,191 @@
<?php
/**
* @group irc
*/
-final class PhabricatorIRCMacroHandler extends PhabricatorIRCHandler {
+final class PhabricatorBotMacroHandler extends PhabricatorBotHandler {
private $macros;
private $regexp;
private $buffer = array();
private $next = 0;
private function init() {
if ($this->macros === false) {
return false;
}
if ($this->macros !== null) {
return true;
}
$macros = $this->getConduit()->callMethodSynchronous(
'macro.query',
array());
// bail if we have no macros
if (empty($macros)) {
return false;
}
$this->macros = $macros;
$regexp = array();
foreach ($this->macros as $macro_name => $macro) {
$regexp[] = preg_quote($macro_name, '/');
}
$regexp = '/('.implode('|', $regexp).')/';
$this->regexp = $regexp;
return true;
}
- public function receiveMessage(PhabricatorIRCMessage $message) {
+ public function receiveMessage(PhabricatorBotMessage $message) {
if (!$this->init()) {
return;
}
switch ($message->getCommand()) {
- case 'PRIVMSG':
- $reply_to = $message->getReplyTo();
- if (!$reply_to) {
- break;
- }
-
- $message = $message->getMessageText();
-
- $matches = null;
- if (!preg_match($this->regexp, $message, $matches)) {
- return;
- }
-
- $macro = $matches[1];
-
- $ascii = idx($this->macros[$macro], 'ascii');
- if ($ascii === false) {
- return;
- }
-
- if (!$ascii) {
- $this->macros[$macro]['ascii'] = $this->rasterize(
- $this->macros[$macro],
- $this->getConfig('macro.size', 48),
- $this->getConfig('macro.aspect', 0.66));
- $ascii = $this->macros[$macro]['ascii'];
- }
-
- foreach ($ascii as $line) {
- $this->buffer[$reply_to][] = $line;
- }
+ case 'MESSAGE':
+ $reply_to = $message->getReplyTo();
+ if (!$reply_to) {
break;
+ }
+
+ $message_body = $message->getBody();
+
+ $matches = null;
+ if (!preg_match($this->regexp, $message_body, $matches)) {
+ return;
+ }
+
+ $macro = $matches[1];
+
+ $ascii = idx($this->macros[$macro], 'ascii');
+ if ($ascii === false) {
+ return;
+ }
+
+ if (!$ascii) {
+ $this->macros[$macro]['ascii'] = $this->rasterize(
+ $this->macros[$macro],
+ $this->getConfig('macro.size', 48),
+ $this->getConfig('macro.aspect', 0.66));
+ $ascii = $this->macros[$macro]['ascii'];
+ }
+
+ foreach ($ascii as $line) {
+ $this->buffer[$reply_to][] = $line;
+ }
+ break;
}
}
public function runBackgroundTasks() {
if (microtime(true) < $this->next) {
return;
}
foreach ($this->buffer as $channel => $lines) {
if (empty($lines)) {
unset($this->buffer[$channel]);
continue;
}
foreach ($lines as $key => $line) {
- $this->write('PRIVMSG', "{$channel} :{$line}");
+ $this->writeMessage(
+ id(new PhabricatorBotMessage())
+ ->setCommand('MESSAGE')
+ ->setTarget($channel)
+ ->setBody($line));
unset($this->buffer[$channel][$key]);
break 2;
}
}
$sleep = $this->getConfig('macro.sleep', 0.25);
$this->next = microtime(true) + ((mt_rand(75, 150) / 100) * $sleep);
}
public function rasterize($macro, $size, $aspect) {
$image = HTTPSFuture::loadContent($macro['uri']);
if (!$image) {
return false;
}
$img = @imagecreatefromstring($image);
if (!$img) {
return false;
}
$sx = imagesx($img);
$sy = imagesy($img);
if ($sx > $size || $sy > $size) {
$scale = max($sx, $sy) / $size;
$dx = floor($sx / $scale);
$dy = floor($sy / $scale);
} else {
$dx = $sx;
$dy = $sy;
}
$dy = floor($dy * $aspect);
$dst = imagecreatetruecolor($dx, $dy);
if (!$dst) {
return false;
}
imagealphablending($dst, false);
$ok = imagecopyresampled(
$dst, $img,
0, 0,
0, 0,
$dx, $dy,
$sx, $sy);
if (!$ok) {
return false;
}
$map = array(
' ',
'.',
',',
':',
';',
'!',
'|',
'*',
'=',
'@',
'$',
'#',
);
$lines = array();
for ($ii = 0; $ii < $dy; $ii++) {
$buf = '';
for ($jj = 0; $jj < $dx; $jj++) {
$c = imagecolorat($dst, $jj, $ii);
$a = ($c >> 24) & 0xFF;
$r = ($c >> 16) & 0xFF;
$g = ($c >> 8) & 0xFF;
$b = ($c) & 0xFF;
$luma = (255 - ((0.30 * $r) + (0.59 * $g) + (0.11 * $b))) / 256;
$luma *= ((127 - $a) / 127);
$char = $map[max(0, floor($luma * count($map)))];
$buf .= $char;
}
$lines[] = $buf;
}
return $lines;
}
}
diff --git a/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php
new file mode 100644
index 0000000000..5a6ff48ad9
--- /dev/null
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotObjectNameHandler.php
@@ -0,0 +1,195 @@
+<?php
+
+/**
+ * Looks for Dxxxx, Txxxx and links to them.
+ *
+ * @group irc
+ */
+final class PhabricatorBotObjectNameHandler extends PhabricatorBotHandler {
+
+ /**
+ * Map of PHIDs to the last mention of them (as an epoch timestamp); prevents
+ * us from spamming chat when a single object is discussed.
+ */
+ private $recentlyMentioned = array();
+
+ public function receiveMessage(PhabricatorBotMessage $original_message) {
+
+ switch ($original_message->getCommand()) {
+ case 'MESSAGE':
+ $message = $original_message->getBody();
+ $matches = null;
+
+ $pattern =
+ '@'.
+ '(?<!/)(?:^|\b)'. // Negative lookbehind prevent matching "/D123".
+ '(D|T|P|V|F)(\d+)'.
+ '(?:\b|$)'.
+ '@';
+
+ $revision_ids = array();
+ $task_ids = array();
+ $paste_ids = array();
+ $commit_names = array();
+ $vote_ids = array();
+ $file_ids = array();
+
+ if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ switch ($match[1]) {
+ case 'D':
+ $revision_ids[] = $match[2];
+ break;
+ case 'T':
+ $task_ids[] = $match[2];
+ break;
+ case 'P':
+ $paste_ids[] = $match[2];
+ break;
+ case 'V':
+ $vote_ids[] = $match[2];
+ break;
+ case 'F':
+ $file_ids[] = $match[2];
+ break;
+ }
+ }
+ }
+
+ $pattern =
+ '@'.
+ '(?<!/)(?:^|\b)'.
+ '(r[A-Z]+[0-9a-z]{1,40})'.
+ '(?:\b|$)'.
+ '@';
+ if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ $commit_names[] = $match[1];
+ }
+ }
+
+ $output = array();
+
+ if ($revision_ids) {
+ $revisions = $this->getConduit()->callMethodSynchronous(
+ 'differential.query',
+ array(
+ 'ids' => $revision_ids,
+ ));
+ $revisions = array_select_keys(
+ ipull($revisions, null, 'id'),
+ $revision_ids
+ );
+ foreach ($revisions as $revision) {
+ $output[$revision['phid']] =
+ 'D'.$revision['id'].' '.$revision['title'].' - '.
+ $revision['uri'];
+ }
+ }
+
+ if ($task_ids) {
+ foreach ($task_ids as $task_id) {
+ if ($task_id == 1000) {
+ $output[1000] = 'T1000: A nanomorph mimetic poly-alloy'
+ .'(liquid metal) assassin controlled by Skynet: '
+ .'http://en.wikipedia.org/wiki/T-1000';
+ continue;
+ }
+ $task = $this->getConduit()->callMethodSynchronous(
+ 'maniphest.info',
+ array(
+ 'task_id' => $task_id,
+ ));
+ $output[$task['phid']] = 'T'.$task['id'].': '.$task['title'].
+ ' (Priority: '.$task['priority'].') - '.$task['uri'];
+ }
+ }
+
+ if ($vote_ids) {
+ foreach ($vote_ids as $vote_id) {
+ $vote = $this->getConduit()->callMethodSynchronous(
+ 'slowvote.info',
+ array(
+ 'poll_id' => $vote_id,
+ ));
+ $output[$vote['phid']] = 'V'.$vote['id'].': '.$vote['question'].
+ ' Come Vote '.$vote['uri'];
+ }
+ }
+
+ if ($file_ids) {
+ foreach ($file_ids as $file_id) {
+ $file = $this->getConduit()->callMethodSynchronous(
+ 'file.info',
+ array(
+ 'id' => $file_id,
+ ));
+ $output[$file['phid']] = $file['objectName'].": ".$file['uri']." - ".
+ $file['name'];
+ }
+ }
+
+ if ($paste_ids) {
+ foreach ($paste_ids as $paste_id) {
+ $paste = $this->getConduit()->callMethodSynchronous(
+ 'paste.info',
+ array(
+ 'paste_id' => $paste_id,
+ ));
+ // Eventually I'd like to show the username of the paster as well,
+ // however that will need something like a user.username_from_phid
+ // since we (ideally) want to keep the bot to Conduit calls...and
+ // not call to Phabricator-specific stuff (like actually loading
+ // the User object and fetching his/her username.)
+ $output[$paste['phid']] = 'P'.$paste['id'].': '.$paste['uri'].' - '.
+ $paste['title'];
+
+ if ($paste['language']) {
+ $output[$paste['phid']] .= ' ('.$paste['language'].')';
+ }
+ }
+ }
+
+ if ($commit_names) {
+ $commits = $this->getConduit()->callMethodSynchronous(
+ 'diffusion.getcommits',
+ array(
+ 'commits' => $commit_names,
+ ));
+ foreach ($commits as $commit) {
+ if (isset($commit['error'])) {
+ continue;
+ }
+ $output[$commit['commitPHID']] = $commit['uri'];
+ }
+ }
+
+ foreach ($output as $phid => $description) {
+
+ // Don't mention the same object more than once every 10 minutes
+ // in public channels, so we avoid spamming the chat over and over
+ // again for discsussions of a specific revision, for example.
+
+ $reply_to = $original_message->getReplyTo();
+ if (empty($this->recentlyMentioned[$reply_to])) {
+ $this->recentlyMentioned[$reply_to] = array();
+ }
+
+ $quiet_until = idx(
+ $this->recentlyMentioned[$reply_to],
+ $phid,
+ 0) + (60 * 10);
+
+ if (time() < $quiet_until) {
+ // Remain quiet on this channel.
+ continue;
+ }
+
+ $this->recentlyMentioned[$reply_to][$phid] = time();
+ $this->replyTo($original_message, $description);
+ }
+ break;
+ }
+ }
+
+}
diff --git a/src/infrastructure/daemon/bot/handler/PhabricatorBotSymbolHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotSymbolHandler.php
new file mode 100644
index 0000000000..536f8713ad
--- /dev/null
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotSymbolHandler.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * Watches for "where is <symbol>?"
+ *
+ * @group irc
+ */
+final class PhabricatorBotSymbolHandler extends PhabricatorBotHandler {
+
+ public function receiveMessage(PhabricatorBotMessage $message) {
+
+ switch ($message->getCommand()) {
+ case 'MESSAGE':
+ $text = $message->getBody();
+
+ $matches = null;
+ if (!preg_match('/where(?: in the world)? is (\S+?)\?/i',
+ $text, $matches)) {
+ break;
+ }
+
+ $symbol = $matches[1];
+ $results = $this->getConduit()->callMethodSynchronous(
+ 'diffusion.findsymbols',
+ array(
+ 'name' => $symbol,
+ ));
+
+ $default_uri = $this->getURI('/diffusion/symbol/'.$symbol.'/');
+
+ if (count($results) > 1) {
+ $response = "Multiple symbols named '{$symbol}': {$default_uri}";
+ } else if (count($results) == 1) {
+ $result = head($results);
+ $response =
+ $result['type'].' '.
+ $result['name'].' '.
+ '('.$result['language'].'): '.
+ nonempty($result['uri'], $default_uri);
+ } else {
+ $response = "No symbol '{$symbol}' found anywhere.";
+ }
+
+ $this->replyTo($message, $response);
+
+ break;
+ }
+ }
+
+}
diff --git a/src/infrastructure/daemon/irc/handler/PhabricatorIRCWhatsNewHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorBotWhatsNewHandler.php
similarity index 82%
rename from src/infrastructure/daemon/irc/handler/PhabricatorIRCWhatsNewHandler.php
rename to src/infrastructure/daemon/bot/handler/PhabricatorBotWhatsNewHandler.php
index d921dca89c..15fc2ecb85 100644
--- a/src/infrastructure/daemon/irc/handler/PhabricatorIRCWhatsNewHandler.php
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorBotWhatsNewHandler.php
@@ -1,147 +1,153 @@
<?php
/**
* Responds to "Whats new?" using the feed.
*
* @group irc
*/
-final class PhabricatorIRCWhatsNewHandler extends PhabricatorIRCHandler {
+final class PhabricatorBotWhatsNewHandler extends PhabricatorBotHandler {
private $floodblock = 0;
- public function receiveMessage(PhabricatorIRCMessage $message) {
+ public function receiveMessage(PhabricatorBotMessage $message) {
switch ($message->getCommand()) {
- case 'PRIVMSG':
+ case 'MESSAGE':
$reply_to = $message->getReplyTo();
if (!$reply_to) {
break;
}
- $message = $message->getMessageText();
+ $message_body = $message->getBody();
$prompt = '~what( i|\')?s new\?~i';
- if (preg_match($prompt, $message)) {
+ if (preg_match($prompt, $message_body)) {
if (time() < $this->floodblock) {
return;
}
$this->floodblock = time() + 60;
$this->getLatest($reply_to);
}
break;
}
}
public function getLatest($reply_to) {
$latest = $this->getConduit()->callMethodSynchronous(
'feed.query',
array(
'limit'=>5
));
$phids = array();
foreach ($latest as $action) {
if (isset($action['data']['actor_phid'])) {
$uid = $action['data']['actor_phid'];
} else {
$uid = $action['authorPHID'];
}
switch ($action['class']) {
case 'PhabricatorFeedStoryDifferential':
$phids[] = $action['data']['revision_phid'];
break;
case 'PhabricatorFeedStoryAudit':
$phids[] = $action['data']['commitPHID'];
break;
case 'PhabricatorFeedStoryManiphest':
$phids[] = $action['data']['taskPHID'];
break;
default:
$phids[] = $uid;
break;
}
array_push($phids,$uid);
}
$infs = $this->getConduit()->callMethodSynchronous(
'phid.query',
array(
'phids'=>$phids
));
$cphid = 0;
foreach ($latest as $action) {
if (isset($action['data']['actor_phid'])) {
$uid = $action['data']['actor_phid'];
} else {
$uid = $action['authorPHID'];
}
switch ($action['class']) {
case 'PhabricatorFeedStoryDifferential':
$rinf = $infs[$action['data']['revision_phid']];
break;
case 'PhabricatorFeedStoryAudit':
$rinf = $infs[$action['data']['commitPHID']];
break;
case 'PhabricatorFeedStoryManiphest':
$rinf = $infs[$action['data']['taskPHID']];
break;
default:
$rinf = array('name'=>$action['class']);
break;
}
$uinf = $infs[$uid];
$action = $this->getRhetoric($action['data']['action']);
$user = $uinf['name'];
$title = $rinf['fullName'];
$uri = $rinf['uri'];
$color = chr(3);
$blue = $color.'12';
$gray = $color.'15';
$bold = chr(2);
$reset = chr(15);
- $content = "{$bold}{$user}{$reset} {$gray}{$action} {$blue}{$bold}".
- "{$title}{$reset} - {$gray}{$uri}{$reset}";
- $this->write('PRIVMSG',"{$reply_to} :{$content}");
+ // Disabling irc-specific styling, at least for now
+ // $content = "{$bold}{$user}{$reset} {$gray}{$action} {$blue}{$bold}".
+ // "{$title}{$reset} - {$gray}{$uri}{$reset}";
+ $content = "{$user} {$action} {$title} - {$uri}";
+ $this->writeMessage(
+ id(new PhabricatorBotMessage())
+ ->setCommand('MESSAGE')
+ ->setTarget($reply_to)
+ ->setBody($content));
}
return;
}
public function getRhetoric($input) {
switch ($input) {
case 'comment':
case 'none':
return 'commented on';
break;
case 'update':
return 'updated';
break;
case 'commit':
return 'closed';
break;
case 'create':
return 'created';
break;
case 'concern':
return 'raised concern for';
break;
case 'abandon':
return 'abandonned';
break;
case 'accept':
return 'accepted';
break;
default:
return $input;
break;
}
}
}
diff --git a/src/infrastructure/daemon/bot/handler/PhabricatorIRCProtocolHandler.php b/src/infrastructure/daemon/bot/handler/PhabricatorIRCProtocolHandler.php
new file mode 100644
index 0000000000..023ffc065f
--- /dev/null
+++ b/src/infrastructure/daemon/bot/handler/PhabricatorIRCProtocolHandler.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * Implements the base IRC protocol so servers don't kick you off.
+ *
+ * @group irc
+ */
+final class PhabricatorIRCProtocolHandler extends PhabricatorBotHandler {
+
+ public function receiveMessage(PhabricatorBotMessage $message) {
+ switch ($message->getCommand()) {
+ case '422': // Error - no MOTD
+ case '376': // End of MOTD
+ $nickpass = $this->getConfig('nickpass');
+ if ($nickpass) {
+ $this->writeMessage(
+ id(new PhabricatorBotMessage())
+ ->setCommand('MESSAGE')
+ ->setTarget('nickserv')
+ ->setBody("IDENTIFY {$nickpass}"));
+ }
+ $join = $this->getConfig('join');
+ if (!$join) {
+ throw new Exception("Not configured to join any channels!");
+ }
+ foreach ($join as $channel) {
+ $this->writeMessage(
+ id(new PhabricatorBotMessage())
+ ->setCommand('JOIN')
+ ->setBody($channel));
+ }
+ break;
+ case 'PING':
+ $this->writeMessage(
+ id(new PhabricatorBotMessage())
+ ->setCommand('PONG')
+ ->setBody($message->getBody()));
+ break;
+ }
+ }
+
+}
diff --git a/src/infrastructure/daemon/irc/PhabricatorIRCBot.php b/src/infrastructure/daemon/irc/PhabricatorIRCBot.php
deleted file mode 100644
index a75352d589..0000000000
--- a/src/infrastructure/daemon/irc/PhabricatorIRCBot.php
+++ /dev/null
@@ -1,250 +0,0 @@
-<?php
-
-/**
- * Simple IRC bot which runs as a Phabricator daemon. Although this bot is
- * somewhat useful, it is also intended to serve as a demo of how to write
- * "system agents" which communicate with Phabricator over Conduit, so you can
- * script system interactions and integrate with other systems.
- *
- * NOTE: This is super janky and experimental right now.
- *
- * @group irc
- */
-final class PhabricatorIRCBot extends PhabricatorDaemon {
-
- private $socket;
- private $handlers;
-
- private $writeBuffer;
- private $readBuffer;
-
- private $conduit;
- private $config;
-
- public function run() {
-
- $argv = $this->getArgv();
- if (count($argv) !== 1) {
- throw new Exception("usage: PhabricatorIRCBot <json_config_file>");
- }
-
- $json_raw = Filesystem::readFile($argv[0]);
- $config = json_decode($json_raw, true);
- if (!is_array($config)) {
- throw new Exception("File '{$argv[0]}' is not valid JSON!");
- }
-
- $server = idx($config, 'server');
- $port = idx($config, 'port', 6667);
- $handlers = idx($config, 'handlers', array());
- $pass = idx($config, 'pass');
- $nick = idx($config, 'nick', 'phabot');
- $user = idx($config, 'user', $nick);
- $ssl = idx($config, 'ssl', false);
- $nickpass = idx($config, 'nickpass');
-
- $this->config = $config;
-
- if (!preg_match('/^[A-Za-z0-9_`[{}^|\]\\-]+$/', $nick)) {
- throw new Exception(
- "Nickname '{$nick}' is invalid!");
- }
-
- foreach ($handlers as $handler) {
- $obj = newv($handler, array($this));
- $this->handlers[] = $obj;
- }
-
- $conduit_uri = idx($config, 'conduit.uri');
- if ($conduit_uri) {
- $conduit_user = idx($config, 'conduit.user');
- $conduit_cert = idx($config, 'conduit.cert');
-
- // Normalize the path component of the URI so users can enter the
- // domain without the "/api/" part.
- $conduit_uri = new PhutilURI($conduit_uri);
- $conduit_uri->setPath('/api/');
- $conduit_uri = (string)$conduit_uri;
-
- $conduit = new ConduitClient($conduit_uri);
- $response = $conduit->callMethodSynchronous(
- 'conduit.connect',
- array(
- 'client' => 'PhabricatorIRCBot',
- 'clientVersion' => '1.0',
- 'clientDescription' => php_uname('n').':'.$nick,
- 'user' => $conduit_user,
- 'certificate' => $conduit_cert,
- ));
-
- $this->conduit = $conduit;
- }
-
- $errno = null;
- $error = null;
- if (!$ssl) {
- $socket = fsockopen($server, $port, $errno, $error);
- } else {
- $socket = fsockopen('ssl://'.$server, $port, $errno, $error);
- }
- if (!$socket) {
- throw new Exception("Failed to connect, #{$errno}: {$error}");
- }
- $ok = stream_set_blocking($socket, false);
- if (!$ok) {
- throw new Exception("Failed to set stream nonblocking.");
- }
-
- $this->socket = $socket;
- $this->writeCommand('USER', "{$user} 0 * :{$user}");
- if ($pass) {
- $this->writeCommand('PASS', "{$pass}");
- }
-
- $this->writeCommand('NICK', "{$nick}");
- $this->runSelectLoop();
- }
-
- public function getConfig($key, $default = null) {
- return idx($this->config, $key, $default);
- }
-
- private function runSelectLoop() {
- do {
- $this->stillWorking();
-
- $read = array($this->socket);
- if (strlen($this->writeBuffer)) {
- $write = array($this->socket);
- } else {
- $write = array();
- }
- $except = array();
-
- $ok = @stream_select($read, $write, $except, $timeout_sec = 1);
- if ($ok === false) {
- throw new Exception(
- "socket_select() failed: ".socket_strerror(socket_last_error()));
- }
-
- if ($read) {
- // Test for connection termination; in PHP, fread() off a nonblocking,
- // closed socket is empty string.
- if (feof($this->socket)) {
- // This indicates the connection was terminated on the other side,
- // just exit via exception and let the overseer restart us after a
- // delay so we can reconnect.
- throw new Exception("Remote host closed connection.");
- }
- do {
- $data = fread($this->socket, 4096);
- if ($data === false) {
- throw new Exception("fread() failed!");
- } else {
- $this->debugLog(true, $data);
- $this->readBuffer .= $data;
- }
- } while (strlen($data));
- }
-
- if ($write) {
- do {
- $len = fwrite($this->socket, $this->writeBuffer);
- if ($len === false) {
- throw new Exception("fwrite() failed!");
- } else {
- $this->debugLog(false, substr($this->writeBuffer, 0, $len));
- $this->writeBuffer = substr($this->writeBuffer, $len);
- }
- } while (strlen($this->writeBuffer));
- }
-
- do {
- $routed_message = $this->processReadBuffer();
- } while ($routed_message);
-
- foreach ($this->handlers as $handler) {
- $handler->runBackgroundTasks();
- }
-
- } while (true);
- }
-
- private function write($message) {
- $this->writeBuffer .= $message;
- return $this;
- }
-
- public function writeCommand($command, $message) {
- return $this->write($command.' '.$message."\r\n");
- }
-
- private function processReadBuffer() {
- $until = strpos($this->readBuffer, "\r\n");
- if ($until === false) {
- return false;
- }
-
- $message = substr($this->readBuffer, 0, $until);
- $this->readBuffer = substr($this->readBuffer, $until + 2);
-
- $pattern =
- '/^'.
- '(?:(?P<sender>:(\S+)) )?'. // This may not be present.
- '(?P<command>[A-Z0-9]+) '.
- '(?P<data>.*)'.
- '$/';
-
- $matches = null;
- if (!preg_match($pattern, $message, $matches)) {
- throw new Exception("Unexpected message from server: {$message}");
- }
-
- $irc_message = new PhabricatorIRCMessage(
- idx($matches, 'sender'),
- $matches['command'],
- $matches['data']);
-
- $this->routeMessage($irc_message);
-
- return true;
- }
-
- private function routeMessage(PhabricatorIRCMessage $message) {
- $ignore = $this->getConfig('ignore');
- if ($ignore && in_array($message->getSenderNickName(), $ignore)) {
- return;
- }
-
- foreach ($this->handlers as $handler) {
- try {
- $handler->receiveMessage($message);
- } catch (Exception $ex) {
- phlog($ex);
- }
- }
- }
-
- public function __destruct() {
- $this->write("QUIT Goodbye.\r\n");
- fclose($this->socket);
- }
-
- private function debugLog($is_read, $message) {
- if ($this->getTraceMode()) {
- echo $is_read ? '<<< ' : '>>> ';
- echo addcslashes($message, "\0..\37\177..\377");
- echo "\n";
- }
- }
-
- public function getConduit() {
- if (empty($this->conduit)) {
- throw new Exception(
- "This bot is not configured with a Conduit uplink. Set 'conduit.uri', ".
- "'conduit.user' and 'conduit.cert' in the configuration to connect.");
- }
- return $this->conduit;
- }
-
-}
diff --git a/src/infrastructure/daemon/irc/PhabricatorIRCMessage.php b/src/infrastructure/daemon/irc/PhabricatorIRCMessage.php
deleted file mode 100644
index 8d3bb14153..0000000000
--- a/src/infrastructure/daemon/irc/PhabricatorIRCMessage.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-
-final class PhabricatorIRCMessage {
-
- private $sender;
- private $command;
- private $data;
-
- public function __construct($sender, $command, $data) {
- $this->sender = $sender;
- $this->command = $command;
- $this->data = $data;
- }
-
- public function getRawSender() {
- return $this->sender;
- }
-
- public function getRawData() {
- return $this->data;
- }
-
- public function getCommand() {
- return $this->command;
- }
-
- public function getReplyTo() {
- switch ($this->getCommand()) {
- case 'PRIVMSG':
- $target = $this->getTarget();
- if ($target[0] == '#') {
- return $target;
- }
- break;
- }
- return null;
- }
-
- public function getSenderNickname() {
- $nick = $this->getRawSender();
- $nick = ltrim($nick, ':');
- $nick = head(explode('!', $nick));
- return $nick;
- }
-
- public function getTarget() {
- switch ($this->getCommand()) {
- case 'PRIVMSG':
- $matches = null;
- $raw = $this->getRawData();
- if (preg_match('/^(\S+)\s/', $raw, $matches)) {
- return $matches[1];
- }
- break;
- }
- return null;
- }
-
- public function getMessageText() {
- switch ($this->getCommand()) {
- case 'PRIVMSG':
- $matches = null;
- $raw = $this->getRawData();
- if (preg_match('/^\S+\s+:?(.*)$/', $raw, $matches)) {
- return rtrim($matches[1], "\r\n");
- }
- break;
- }
- return null;
- }
-
-}
diff --git a/src/infrastructure/daemon/irc/handler/PhabricatorIRCHandler.php b/src/infrastructure/daemon/irc/handler/PhabricatorIRCHandler.php
deleted file mode 100644
index 8f059bed67..0000000000
--- a/src/infrastructure/daemon/irc/handler/PhabricatorIRCHandler.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-
-/**
- * Responds to IRC messages. You plug a bunch of these into a
- * @{class:PhabricatorIRCBot} to give it special behavior.
- *
- * @group irc
- */
-abstract class PhabricatorIRCHandler {
-
- private $bot;
-
- final public function __construct(PhabricatorIRCBot $irc_bot) {
- $this->bot = $irc_bot;
- }
-
- final protected function write($command, $message) {
- $this->bot->writeCommand($command, $message);
- return $this;
- }
-
- final protected function getConduit() {
- return $this->bot->getConduit();
- }
-
- final protected function getConfig($key, $default = null) {
- return $this->bot->getConfig($key, $default);
- }
-
- final protected function getURI($path) {
- $base_uri = new PhutilURI($this->bot->getConfig('conduit.uri'));
- $base_uri->setPath($path);
- return (string)$base_uri;
- }
-
- final protected function isChannelName($name) {
- return (strncmp($name, '#', 1) === 0);
- }
-
- abstract public function receiveMessage(PhabricatorIRCMessage $message);
-
- public function runBackgroundTasks() {
- return;
- }
-
-}
diff --git a/src/infrastructure/daemon/irc/handler/PhabricatorIRCObjectNameHandler.php b/src/infrastructure/daemon/irc/handler/PhabricatorIRCObjectNameHandler.php
deleted file mode 100644
index ba551d1d33..0000000000
--- a/src/infrastructure/daemon/irc/handler/PhabricatorIRCObjectNameHandler.php
+++ /dev/null
@@ -1,199 +0,0 @@
-<?php
-
-/**
- * Looks for Dxxxx, Txxxx and links to them.
- *
- * @group irc
- */
-final class PhabricatorIRCObjectNameHandler extends PhabricatorIRCHandler {
-
- /**
- * Map of PHIDs to the last mention of them (as an epoch timestamp); prevents
- * us from spamming chat when a single object is discussed.
- */
- private $recentlyMentioned = array();
-
- public function receiveMessage(PhabricatorIRCMessage $message) {
-
- switch ($message->getCommand()) {
- case 'PRIVMSG':
- $reply_to = $message->getReplyTo();
- if (!$reply_to) {
- break;
- }
-
- $message = $message->getMessageText();
- $matches = null;
-
- $pattern =
- '@'.
- '(?<!/)(?:^|\b)'. // Negative lookbehind prevent matching "/D123".
- '(D|T|P|V|F)(\d+)'.
- '(?:\b|$)'.
- '@';
-
- $revision_ids = array();
- $task_ids = array();
- $paste_ids = array();
- $commit_names = array();
- $vote_ids = array();
- $file_ids = array();
-
- if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) {
- foreach ($matches as $match) {
- switch ($match[1]) {
- case 'D':
- $revision_ids[] = $match[2];
- break;
- case 'T':
- $task_ids[] = $match[2];
- break;
- case 'P':
- $paste_ids[] = $match[2];
- break;
- case 'V':
- $vote_ids[] = $match[2];
- break;
- case 'F':
- $file_ids[] = $match[2];
- break;
- }
- }
- }
-
- $pattern =
- '@'.
- '(?<!/)(?:^|\b)'.
- '(r[A-Z]+[0-9a-z]{1,40})'.
- '(?:\b|$)'.
- '@';
- if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) {
- foreach ($matches as $match) {
- $commit_names[] = $match[1];
- }
- }
-
- $output = array();
-
- if ($revision_ids) {
- $revisions = $this->getConduit()->callMethodSynchronous(
- 'differential.query',
- array(
- 'ids' => $revision_ids,
- ));
- $revisions = array_select_keys(
- ipull($revisions, null, 'id'),
- $revision_ids
- );
- foreach ($revisions as $revision) {
- $output[$revision['phid']] =
- 'D'.$revision['id'].' '.$revision['title'].' - '.
- $revision['uri'];
- }
- }
-
- if ($task_ids) {
- foreach ($task_ids as $task_id) {
- if ($task_id == 1000) {
- $output[1000] = 'T1000: A nanomorph mimetic poly-alloy'
- .'(liquid metal) assassin controlled by Skynet: '
- .'http://en.wikipedia.org/wiki/T-1000';
- continue;
- }
- $task = $this->getConduit()->callMethodSynchronous(
- 'maniphest.info',
- array(
- 'task_id' => $task_id,
- ));
- $output[$task['phid']] = 'T'.$task['id'].': '.$task['title'].
- ' (Priority: '.$task['priority'].') - '.$task['uri'];
- }
- }
-
- if ($vote_ids) {
- foreach ($vote_ids as $vote_id) {
- $vote = $this->getConduit()->callMethodSynchronous(
- 'slowvote.info',
- array(
- 'poll_id' => $vote_id,
- ));
- $output[$vote['phid']] = 'V'.$vote['id'].': '.$vote['question'].
- ' Come Vote '.$vote['uri'];
- }
- }
-
- if ($file_ids) {
- foreach ($file_ids as $file_id) {
- $file = $this->getConduit()->callMethodSynchronous(
- 'file.info',
- array(
- 'id' => $file_id,
- ));
- $output[$file['phid']] = $file['objectName'].": ".$file['uri']." - ".
- $file['name'];
- }
- }
-
- if ($paste_ids) {
- foreach ($paste_ids as $paste_id) {
- $paste = $this->getConduit()->callMethodSynchronous(
- 'paste.info',
- array(
- 'paste_id' => $paste_id,
- ));
- // Eventually I'd like to show the username of the paster as well,
- // however that will need something like a user.username_from_phid
- // since we (ideally) want to keep the bot to Conduit calls...and
- // not call to Phabricator-specific stuff (like actually loading
- // the User object and fetching his/her username.)
- $output[$paste['phid']] = 'P'.$paste['id'].': '.$paste['uri'].' - '.
- $paste['title'];
-
- if ($paste['language']) {
- $output[$paste['phid']] .= ' ('.$paste['language'].')';
- }
- }
- }
-
- if ($commit_names) {
- $commits = $this->getConduit()->callMethodSynchronous(
- 'diffusion.getcommits',
- array(
- 'commits' => $commit_names,
- ));
- foreach ($commits as $commit) {
- if (isset($commit['error'])) {
- continue;
- }
- $output[$commit['commitPHID']] = $commit['uri'];
- }
- }
-
- foreach ($output as $phid => $description) {
-
- // Don't mention the same object more than once every 10 minutes
- // in public channels, so we avoid spamming the chat over and over
- // again for discsussions of a specific revision, for example.
-
- if (empty($this->recentlyMentioned[$reply_to])) {
- $this->recentlyMentioned[$reply_to] = array();
- }
-
- $quiet_until = idx(
- $this->recentlyMentioned[$reply_to],
- $phid,
- 0) + (60 * 10);
-
- if (time() < $quiet_until) {
- // Remain quiet on this channel.
- continue;
- }
-
- $this->recentlyMentioned[$reply_to][$phid] = time();
- $this->write('PRIVMSG', "{$reply_to} :{$description}");
- }
- break;
- }
- }
-
-}
diff --git a/src/infrastructure/daemon/irc/handler/PhabricatorIRCProtocolHandler.php b/src/infrastructure/daemon/irc/handler/PhabricatorIRCProtocolHandler.php
deleted file mode 100644
index 1347d2bbdc..0000000000
--- a/src/infrastructure/daemon/irc/handler/PhabricatorIRCProtocolHandler.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-
-/**
- * Implements the base IRC protocol so servers don't kick you off.
- *
- * @group irc
- */
-final class PhabricatorIRCProtocolHandler extends PhabricatorIRCHandler {
-
- public function receiveMessage(PhabricatorIRCMessage $message) {
- switch ($message->getCommand()) {
- case '422': // Error - no MOTD
- case '376': // End of MOTD
- $nickpass = $this->getConfig('nickpass');
- if ($nickpass) {
- $this->write('PRIVMSG', "nickserv :IDENTIFY {$nickpass}");
- }
- $join = $this->getConfig('join');
- if (!$join) {
- throw new Exception("Not configured to join any channels!");
- }
- foreach ($join as $channel) {
- $this->write('JOIN', $channel);
- }
- break;
- case 'PING':
- $this->write('PONG', $message->getRawData());
- break;
- }
- }
-
-}
diff --git a/src/infrastructure/daemon/irc/handler/PhabricatorIRCSymbolHandler.php b/src/infrastructure/daemon/irc/handler/PhabricatorIRCSymbolHandler.php
deleted file mode 100644
index 8b4343d3ed..0000000000
--- a/src/infrastructure/daemon/irc/handler/PhabricatorIRCSymbolHandler.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-
-/**
- * Watches for "where is <symbol>?"
- *
- * @group irc
- */
-final class PhabricatorIRCSymbolHandler extends PhabricatorIRCHandler {
-
- public function receiveMessage(PhabricatorIRCMessage $message) {
-
- switch ($message->getCommand()) {
- case 'PRIVMSG':
- $reply_to = $message->getReplyTo();
- if (!$reply_to) {
- break;
- }
-
- $text = $message->getMessageText();
-
- $matches = null;
- if (!preg_match('/where(?: in the world)? is (\S+?)\?/i',
- $text, $matches)) {
- break;
- }
-
- $symbol = $matches[1];
- $results = $this->getConduit()->callMethodSynchronous(
- 'diffusion.findsymbols',
- array(
- 'name' => $symbol,
- ));
-
- $default_uri = $this->getURI('/diffusion/symbol/'.$symbol.'/');
-
- if (count($results) > 1) {
- $response = "Multiple symbols named '{$symbol}': {$default_uri}";
- } else if (count($results) == 1) {
- $result = head($results);
- $response =
- $result['type'].' '.
- $result['name'].' '.
- '('.$result['language'].'): '.
- nonempty($result['uri'], $default_uri);
- } else {
- $response = "No symbol '{$symbol}' found anywhere.";
- }
-
- $this->write('PRIVMSG', "{$reply_to} :{$response}");
-
- break;
- }
- }
-
-}
diff --git a/src/infrastructure/events/constant/PhabricatorEventType.php b/src/infrastructure/events/constant/PhabricatorEventType.php
index 39772ea4e4..f6f91e9e82 100644
--- a/src/infrastructure/events/constant/PhabricatorEventType.php
+++ b/src/infrastructure/events/constant/PhabricatorEventType.php
@@ -1,33 +1,34 @@
<?php
/**
* For detailed explanations of these events, see
* @{article:Events User Guide: Installing Event Listeners}.
*
* @group events
*/
final class PhabricatorEventType extends PhutilEventType {
const TYPE_CONTROLLER_CHECKREQUEST = 'controller.checkRequest';
const TYPE_MANIPHEST_WILLEDITTASK = 'maniphest.willEditTask';
const TYPE_MANIPHEST_DIDEDITTASK = 'maniphest.didEditTask';
const TYPE_DIFFERENTIAL_WILLSENDMAIL = 'differential.willSendMail';
const TYPE_DIFFERENTIAL_WILLMARKGENERATED = 'differential.willMarkGenerated';
const TYPE_DIFFUSION_DIDDISCOVERCOMMIT = 'diffusion.didDiscoverCommit';
const TYPE_DIFFUSION_LOOKUPUSER = 'diffusion.lookupUser';
const TYPE_EDGE_WILLEDITEDGES = 'edge.willEditEdges';
const TYPE_EDGE_DIDEDITEDGES = 'edge.didEditEdges';
const TYPE_TEST_DIDRUNTEST = 'test.didRunTest';
const TYPE_UI_DIDRENDERACTIONS = 'ui.didRenderActions';
const TYPE_UI_WILLRENDEROBJECTS = 'ui.willRenderObjects';
const TYPE_UI_DDIDRENDEROBJECT = 'ui.didRenderObject';
const TYPE_UI_DIDRENDEROBJECTS = 'ui.didRenderObjects';
+ const TYPE_PEOPLE_DIDRENDERMENU = 'people.didRenderMenu';
}
diff --git a/src/infrastructure/markup/rule/PhabricatorRemarkupRuleEmbedFile.php b/src/infrastructure/markup/rule/PhabricatorRemarkupRuleEmbedFile.php
index 4129d432aa..9ef0ac8ad9 100644
--- a/src/infrastructure/markup/rule/PhabricatorRemarkupRuleEmbedFile.php
+++ b/src/infrastructure/markup/rule/PhabricatorRemarkupRuleEmbedFile.php
@@ -1,183 +1,187 @@
<?php
/**
* @group markup
*/
final class PhabricatorRemarkupRuleEmbedFile
extends PhutilRemarkupRule {
const KEY_RULE_EMBED_FILE = 'rule.embed.file';
const KEY_EMBED_FILE_PHIDS = 'phabricator.embedded-file-phids';
public function apply($text) {
return preg_replace_callback(
"@{F(\d+)([^}]+?)?}@",
array($this, 'markupEmbedFile'),
$text);
}
public function markupEmbedFile($matches) {
$file = null;
if ($matches[1]) {
// TODO: This is pretty inefficient if there are a bunch of files.
$file = id(new PhabricatorFile())->load($matches[1]);
}
if (!$file) {
return $matches[0];
}
$phid = $file->getPHID();
$engine = $this->getEngine();
$token = $engine->storeText('');
$metadata_key = self::KEY_RULE_EMBED_FILE;
$metadata = $engine->getTextMetadata($metadata_key, array());
$bundle = array('token' => $token);
$options = array(
'size' => 'thumb',
'layout' => 'left',
'float' => false,
'name' => null,
);
if (!empty($matches[2])) {
$matches[2] = trim($matches[2], ', ');
$parser = new PhutilSimpleOptions();
$options = $parser->parse($matches[2]) + $options;
}
$file_name = coalesce($options['name'], $file->getName());
$options['name'] = $file_name;
+ $is_viewable_image = $file->isViewableImage();
+
$attrs = array();
- switch ((string)$options['size']) {
- case 'full':
- $attrs['src'] = $file->getBestURI();
- $options['image_class'] = null;
- $file_data = $file->getMetadata();
- $height = idx($file_data, PhabricatorFile::METADATA_IMAGE_HEIGHT);
- if ($height) {
- $attrs['height'] = $height;
- }
- $width = idx($file_data, PhabricatorFile::METADATA_IMAGE_WIDTH);
- if ($width) {
- $attrs['width'] = $width;
- }
- break;
- case 'thumb':
- default:
- $attrs['src'] = $file->getPreview220URI();
- $dimensions =
- PhabricatorImageTransformer::getPreviewDimensions($file, 220);
- $attrs['width'] = $dimensions['sdx'];
- $attrs['height'] = $dimensions['sdy'];
- $options['image_class'] = 'phabricator-remarkup-embed-image';
- break;
+ if ($is_viewable_image) {
+ switch ((string)$options['size']) {
+ case 'full':
+ $attrs['src'] = $file->getBestURI();
+ $options['image_class'] = null;
+ $file_data = $file->getMetadata();
+ $height = idx($file_data, PhabricatorFile::METADATA_IMAGE_HEIGHT);
+ if ($height) {
+ $attrs['height'] = $height;
+ }
+ $width = idx($file_data, PhabricatorFile::METADATA_IMAGE_WIDTH);
+ if ($width) {
+ $attrs['width'] = $width;
+ }
+ break;
+ case 'thumb':
+ default:
+ $attrs['src'] = $file->getPreview220URI();
+ $dimensions =
+ PhabricatorImageTransformer::getPreviewDimensions($file, 220);
+ $attrs['width'] = $dimensions['sdx'];
+ $attrs['height'] = $dimensions['sdy'];
+ $options['image_class'] = 'phabricator-remarkup-embed-image';
+ break;
+ }
}
$bundle['attrs'] = $attrs;
$bundle['options'] = $options;
$bundle['meta'] = array(
'phid' => $file->getPHID(),
- 'viewable' => $file->isViewableImage(),
+ 'viewable' => $is_viewable_image,
'uri' => $file->getBestURI(),
'dUri' => $file->getDownloadURI(),
'name' => $options['name'],
);
$metadata[$phid][] = $bundle;
$engine->setTextMetadata($metadata_key, $metadata);
return $token;
}
public function didMarkupText() {
$engine = $this->getEngine();
$metadata_key = self::KEY_RULE_EMBED_FILE;
$metadata = $engine->getTextMetadata($metadata_key, array());
if (!$metadata) {
return;
}
$file_phids = array();
foreach ($metadata as $phid => $bundles) {
foreach ($bundles as $data) {
$options = $data['options'];
$meta = $data['meta'];
if (!$meta['viewable'] || $options['layout'] == 'link') {
$link = id(new PhabricatorFileLinkView())
->setFilePHID($meta['phid'])
->setFileName($meta['name'])
->setFileDownloadURI($meta['dUri'])
->setFileViewURI($meta['uri'])
->setFileViewable($meta['viewable']);
$embed = $link->render();
$engine->overwriteStoredText($data['token'], $embed);
continue;
}
require_celerity_resource('lightbox-attachment-css');
$img = phutil_tag('img', $data['attrs']);
$embed = javelin_tag(
'a',
array(
'href' => $meta['uri'],
'class' => $options['image_class'],
'sigil' => 'lightboxable',
'mustcapture' => true,
'meta' => $meta,
),
$img);
$layout_class = null;
switch ($options['layout']) {
case 'right':
case 'center':
case 'inline':
case 'left':
$layout_class = 'phabricator-remarkup-embed-layout-'.
$options['layout'];
break;
default:
$layout_class = 'phabricator-remarkup-embed-layout-left';
break;
}
if ($options['float']) {
switch ($options['layout']) {
case 'center':
case 'inline':
break;
case 'right':
$layout_class .= ' phabricator-remarkup-embed-float-right';
break;
case 'left':
default:
$layout_class .= ' phabricator-remarkup-embed-float-left';
break;
}
}
if ($layout_class) {
$embed = phutil_tag(
'div',
array(
'class' => $layout_class,
),
$embed);
}
$engine->overwriteStoredText($data['token'], $embed);
}
$file_phids[] = $phid;
}
$engine->setTextMetadata(self::KEY_EMBED_FILE_PHIDS, $file_phids);
$engine->setTextMetadata($metadata_key, array());
}
}
diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
index 71dbe66291..029f30fe0a 100644
--- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
+++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
@@ -1,1111 +1,1115 @@
<?php
final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
public function getNamespace() {
return 'phabricator';
}
private function getPatchPath($file) {
$root = dirname(phutil_get_library_root('phabricator'));
$path = $root.'/resources/sql/patches/'.$file;
// Make sure it exists.
Filesystem::readFile($path);
return $path;
}
public function getPatches() {
return array(
'db.audit' => array(
'type' => 'db',
'name' => 'audit',
'after' => array( /* First Patch */ ),
),
'db.calendar' => array(
'type' => 'db',
'name' => 'calendar',
),
'db.chatlog' => array(
'type' => 'db',
'name' => 'chatlog',
),
'db.conduit' => array(
'type' => 'db',
'name' => 'conduit',
),
'db.countdown' => array(
'type' => 'db',
'name' => 'countdown',
),
'db.daemon' => array(
'type' => 'db',
'name' => 'daemon',
),
'db.differential' => array(
'type' => 'db',
'name' => 'differential',
),
'db.draft' => array(
'type' => 'db',
'name' => 'draft',
),
'db.drydock' => array(
'type' => 'db',
'name' => 'drydock',
),
'db.feed' => array(
'type' => 'db',
'name' => 'feed',
),
'db.file' => array(
'type' => 'db',
'name' => 'file',
),
'db.flag' => array(
'type' => 'db',
'name' => 'flag',
),
'db.harbormaster' => array(
'type' => 'db',
'name' => 'harbormaster',
),
'db.herald' => array(
'type' => 'db',
'name' => 'herald',
),
'db.maniphest' => array(
'type' => 'db',
'name' => 'maniphest',
),
'db.meta_data' => array(
'type' => 'db',
'name' => 'meta_data',
),
'db.metamta' => array(
'type' => 'db',
'name' => 'metamta',
),
'db.oauth_server' => array(
'type' => 'db',
'name' => 'oauth_server',
),
'db.owners' => array(
'type' => 'db',
'name' => 'owners',
),
'db.pastebin' => array(
'type' => 'db',
'name' => 'pastebin',
),
'db.phame' => array(
'type' => 'db',
'name' => 'phame',
),
'db.phriction' => array(
'type' => 'db',
'name' => 'phriction',
),
'db.project' => array(
'type' => 'db',
'name' => 'project',
),
'db.repository' => array(
'type' => 'db',
'name' => 'repository',
),
'db.search' => array(
'type' => 'db',
'name' => 'search',
),
'db.slowvote' => array(
'type' => 'db',
'name' => 'slowvote',
),
'db.timeline' => array(
'type' => 'db',
'name' => 'timeline',
),
'db.user' => array(
'type' => 'db',
'name' => 'user',
),
'db.worker' => array(
'type' => 'db',
'name' => 'worker',
),
'db.xhpastview' => array(
'type' => 'db',
'name' => 'xhpastview',
),
'db.cache' => array(
'type' => 'db',
'name' => 'cache',
),
'db.fact' => array(
'type' => 'db',
'name' => 'fact',
),
'db.ponder' => array(
'type' => 'db',
'name' => 'ponder',
),
'db.xhprof' => array(
'type' => 'db',
'name' => 'xhprof',
),
'db.pholio' => array(
'type' => 'db',
'name' => 'pholio',
),
'db.conpherence' => array(
'type' => 'db',
'name' => 'conpherence',
),
'0000.legacy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('0000.legacy.sql'),
'legacy' => 0,
),
'000.project.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('000.project.sql'),
'legacy' => 0,
),
'001.maniphest_projects.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('001.maniphest_projects.sql'),
'legacy' => 1,
),
'002.oauth.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('002.oauth.sql'),
'legacy' => 2,
),
'003.more_oauth.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('003.more_oauth.sql'),
'legacy' => 3,
),
'004.daemonrepos.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('004.daemonrepos.sql'),
'legacy' => 4,
),
'005.workers.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('005.workers.sql'),
'legacy' => 5,
),
'006.repository.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('006.repository.sql'),
'legacy' => 6,
),
'007.daemonlog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('007.daemonlog.sql'),
'legacy' => 7,
),
'008.repoopt.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('008.repoopt.sql'),
'legacy' => 8,
),
'009.repo_summary.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('009.repo_summary.sql'),
'legacy' => 9,
),
'010.herald.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('010.herald.sql'),
'legacy' => 10,
),
'011.badcommit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('011.badcommit.sql'),
'legacy' => 11,
),
'012.dropphidtype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('012.dropphidtype.sql'),
'legacy' => 12,
),
'013.commitdetail.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('013.commitdetail.sql'),
'legacy' => 13,
),
'014.shortcuts.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('014.shortcuts.sql'),
'legacy' => 14,
),
'015.preferences.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('015.preferences.sql'),
'legacy' => 15,
),
'016.userrealnameindex.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('016.userrealnameindex.sql'),
'legacy' => 16,
),
'017.sessionkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('017.sessionkeys.sql'),
'legacy' => 17,
),
'018.owners.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('018.owners.sql'),
'legacy' => 18,
),
'019.arcprojects.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('019.arcprojects.sql'),
'legacy' => 19,
),
'020.pathcapital.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('020.pathcapital.sql'),
'legacy' => 20,
),
'021.xhpastview.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('021.xhpastview.sql'),
'legacy' => 21,
),
'022.differentialcommit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('022.differentialcommit.sql'),
'legacy' => 22,
),
'023.dxkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('023.dxkeys.sql'),
'legacy' => 23,
),
'024.mlistkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('024.mlistkeys.sql'),
'legacy' => 24,
),
'025.commentopt.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('025.commentopt.sql'),
'legacy' => 25,
),
'026.diffpropkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('026.diffpropkey.sql'),
'legacy' => 26,
),
'027.metamtakeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('027.metamtakeys.sql'),
'legacy' => 27,
),
'028.systemagent.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('028.systemagent.sql'),
'legacy' => 28,
),
'029.cursors.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('029.cursors.sql'),
'legacy' => 29,
),
'030.imagemacro.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('030.imagemacro.sql'),
'legacy' => 30,
),
'031.workerrace.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('031.workerrace.sql'),
'legacy' => 31,
),
'032.viewtime.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('032.viewtime.sql'),
'legacy' => 32,
),
'033.privtest.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('033.privtest.sql'),
'legacy' => 33,
),
'034.savedheader.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('034.savedheader.sql'),
'legacy' => 34,
),
'035.proxyimage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('035.proxyimage.sql'),
'legacy' => 35,
),
'036.mailkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('036.mailkey.sql'),
'legacy' => 36,
),
'037.setuptest.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('037.setuptest.sql'),
'legacy' => 37,
),
'038.admin.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('038.admin.sql'),
'legacy' => 38,
),
'039.userlog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('039.userlog.sql'),
'legacy' => 39,
),
'040.transform.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('040.transform.sql'),
'legacy' => 40,
),
'041.heraldrepetition.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('041.heraldrepetition.sql'),
'legacy' => 41,
),
'042.commentmetadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('042.commentmetadata.sql'),
'legacy' => 42,
),
'043.pastebin.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('043.pastebin.sql'),
'legacy' => 43,
),
'044.countdown.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('044.countdown.sql'),
'legacy' => 44,
),
'045.timezone.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('045.timezone.sql'),
'legacy' => 45,
),
'046.conduittoken.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('046.conduittoken.sql'),
'legacy' => 46,
),
'047.projectstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('047.projectstatus.sql'),
'legacy' => 47,
),
'048.relationshipkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('048.relationshipkeys.sql'),
'legacy' => 48,
),
'049.projectowner.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('049.projectowner.sql'),
'legacy' => 49,
),
'050.taskdenormal.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('050.taskdenormal.sql'),
'legacy' => 50,
),
'051.projectfilter.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('051.projectfilter.sql'),
'legacy' => 51,
),
'052.pastelanguage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('052.pastelanguage.sql'),
'legacy' => 52,
),
'053.feed.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('053.feed.sql'),
'legacy' => 53,
),
'054.subscribers.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('054.subscribers.sql'),
'legacy' => 54,
),
'055.add_author_to_files.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('055.add_author_to_files.sql'),
'legacy' => 55,
),
'056.slowvote.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('056.slowvote.sql'),
'legacy' => 56,
),
'057.parsecache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('057.parsecache.sql'),
'legacy' => 57,
),
'058.missingkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('058.missingkeys.sql'),
'legacy' => 58,
),
'059.engines.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('059.engines.php'),
'legacy' => 59,
),
'060.phriction.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('060.phriction.sql'),
'legacy' => 60,
),
'061.phrictioncontent.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('061.phrictioncontent.sql'),
'legacy' => 61,
),
'062.phrictionmenu.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('062.phrictionmenu.sql'),
'legacy' => 62,
),
'063.pasteforks.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('063.pasteforks.sql'),
'legacy' => 63,
),
'064.subprojects.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('064.subprojects.sql'),
'legacy' => 64,
),
'065.sshkeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('065.sshkeys.sql'),
'legacy' => 65,
),
'066.phrictioncontent.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('066.phrictioncontent.sql'),
'legacy' => 66,
),
'067.preferences.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('067.preferences.sql'),
'legacy' => 67,
),
'068.maniphestauxiliarystorage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('068.maniphestauxiliarystorage.sql'),
'legacy' => 68,
),
'069.heraldxscript.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('069.heraldxscript.sql'),
'legacy' => 69,
),
'070.differentialaux.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('070.differentialaux.sql'),
'legacy' => 70,
),
'071.contentsource.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('071.contentsource.sql'),
'legacy' => 71,
),
'072.blamerevert.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('072.blamerevert.sql'),
'legacy' => 72,
),
'073.reposymbols.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('073.reposymbols.sql'),
'legacy' => 73,
),
'074.affectedpath.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('074.affectedpath.sql'),
'legacy' => 74,
),
'075.revisionhash.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('075.revisionhash.sql'),
'legacy' => 75,
),
'076.indexedlanguages.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('076.indexedlanguages.sql'),
'legacy' => 76,
),
'077.originalemail.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('077.originalemail.sql'),
'legacy' => 77,
),
'078.nametoken.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('078.nametoken.sql'),
'legacy' => 78,
),
'079.nametokenindex.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('079.nametokenindex.php'),
'legacy' => 79,
),
'080.filekeys.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('080.filekeys.sql'),
'legacy' => 80,
),
'081.filekeys.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('081.filekeys.php'),
'legacy' => 81,
),
'082.xactionkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('082.xactionkey.sql'),
'legacy' => 82,
),
'083.dxviewtime.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('083.dxviewtime.sql'),
'legacy' => 83,
),
'084.pasteauthorkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('084.pasteauthorkey.sql'),
'legacy' => 84,
),
'085.packagecommitrelationship.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('085.packagecommitrelationship.sql'),
'legacy' => 85,
),
'086.formeraffil.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('086.formeraffil.sql'),
'legacy' => 86,
),
'087.phrictiondelete.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('087.phrictiondelete.sql'),
'legacy' => 87,
),
'088.audit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('088.audit.sql'),
'legacy' => 88,
),
'089.projectwiki.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('089.projectwiki.sql'),
'legacy' => 89,
),
'090.forceuniqueprojectnames.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('090.forceuniqueprojectnames.php'),
'legacy' => 90,
),
'091.uniqueslugkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('091.uniqueslugkey.sql'),
'legacy' => 91,
),
'092.dropgithubnotification.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('092.dropgithubnotification.sql'),
'legacy' => 92,
),
'093.gitremotes.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('093.gitremotes.php'),
'legacy' => 93,
),
'094.phrictioncolumn.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('094.phrictioncolumn.sql'),
'legacy' => 94,
),
'095.directory.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('095.directory.sql'),
'legacy' => 95,
),
'096.filename.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('096.filename.sql'),
'legacy' => 96,
),
'097.heraldruletypes.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('097.heraldruletypes.sql'),
'legacy' => 97,
),
'098.heraldruletypemigration.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('098.heraldruletypemigration.php'),
'legacy' => 98,
),
'099.drydock.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('099.drydock.sql'),
'legacy' => 99,
),
'100.projectxaction.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('100.projectxaction.sql'),
'legacy' => 100,
),
'101.heraldruleapplied.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('101.heraldruleapplied.sql'),
'legacy' => 101,
),
'102.heraldcleanup.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('102.heraldcleanup.php'),
'legacy' => 102,
),
'103.heraldedithistory.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('103.heraldedithistory.sql'),
'legacy' => 103,
),
'104.searchkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('104.searchkey.sql'),
'legacy' => 104,
),
'105.mimetype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('105.mimetype.sql'),
'legacy' => 105,
),
'106.chatlog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('106.chatlog.sql'),
'legacy' => 106,
),
'107.oauthserver.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('107.oauthserver.sql'),
'legacy' => 107,
),
'108.oauthscope.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('108.oauthscope.sql'),
'legacy' => 108,
),
'109.oauthclientphidkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('109.oauthclientphidkey.sql'),
'legacy' => 109,
),
'110.commitaudit.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('110.commitaudit.sql'),
'legacy' => 110,
),
'111.commitauditmigration.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('111.commitauditmigration.php'),
'legacy' => 111,
),
'112.oauthaccesscoderedirecturi.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('112.oauthaccesscoderedirecturi.sql'),
'legacy' => 112,
),
'113.lastreviewer.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('113.lastreviewer.sql'),
'legacy' => 113,
),
'114.auditrequest.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('114.auditrequest.sql'),
'legacy' => 114,
),
'115.prepareutf8.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('115.prepareutf8.sql'),
'legacy' => 115,
),
'116.utf8-backup-first-expect-wait.sql' => array(
'type' => 'sql',
'name' =>
$this->getPatchPath('116.utf8-backup-first-expect-wait.sql'),
'legacy' => 116,
),
'117.repositorydescription.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('117.repositorydescription.php'),
'legacy' => 117,
),
'118.auditinline.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('118.auditinline.sql'),
'legacy' => 118,
),
'119.filehash.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('119.filehash.sql'),
'legacy' => 119,
),
'120.noop.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('120.noop.sql'),
'legacy' => 120,
),
'121.drydocklog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('121.drydocklog.sql'),
'legacy' => 121,
),
'122.flag.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('122.flag.sql'),
'legacy' => 122,
),
'123.heraldrulelog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('123.heraldrulelog.sql'),
'legacy' => 123,
),
'124.subpriority.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('124.subpriority.sql'),
'legacy' => 124,
),
'125.ipv6.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('125.ipv6.sql'),
'legacy' => 125,
),
'126.edges.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('126.edges.sql'),
'legacy' => 126,
),
'127.userkeybody.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('127.userkeybody.sql'),
'legacy' => 127,
),
'128.phabricatorcom.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('128.phabricatorcom.sql'),
'legacy' => 128,
),
'129.savedquery.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('129.savedquery.sql'),
'legacy' => 129,
),
'130.denormalrevisionquery.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('130.denormalrevisionquery.sql'),
'legacy' => 130,
),
'131.migraterevisionquery.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('131.migraterevisionquery.php'),
'legacy' => 131,
),
'132.phame.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('132.phame.sql'),
'legacy' => 132,
),
'133.imagemacro.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('133.imagemacro.sql'),
'legacy' => 133,
),
'134.emptysearch.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('134.emptysearch.sql'),
'legacy' => 134,
),
'135.datecommitted.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('135.datecommitted.sql'),
'legacy' => 135,
),
'136.sex.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('136.sex.sql'),
'legacy' => 136,
),
'137.auditmetadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('137.auditmetadata.sql'),
'legacy' => 137,
),
'138.notification.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('138.notification.sql'),
),
'holidays.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('holidays.sql'),
),
'userstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('userstatus.sql'),
),
'emailtable.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('emailtable.sql'),
),
'emailtableport.sql' => array(
'type' => 'php',
'name' => $this->getPatchPath('emailtableport.php'),
),
'emailtableremove.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('emailtableremove.sql'),
),
'phiddrop.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phiddrop.sql'),
),
'testdatabase.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('testdatabase.sql'),
),
'ldapinfo.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ldapinfo.sql'),
),
'threadtopic.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('threadtopic.sql'),
),
'usertranslation.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('usertranslation.sql'),
),
'differentialbookmarks.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('differentialbookmarks.sql'),
),
'harbormasterobject.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('harbormasterobject.sql'),
),
'markupcache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('markupcache.sql'),
),
'maniphestxcache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('maniphestxcache.sql'),
),
'migrate-maniphest-dependencies.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('migrate-maniphest-dependencies.php'),
),
'migrate-differential-dependencies.php' => array(
'type' => 'php',
'name' => $this->getPatchPath(
'migrate-differential-dependencies.php'),
),
'phameblog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phameblog.sql'),
),
'migrate-maniphest-revisions.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('migrate-maniphest-revisions.php'),
),
'daemonstatus.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('daemonstatus.sql'),
),
'symbolcontexts.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('symbolcontexts.sql'),
),
'migrate-project-edges.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('migrate-project-edges.php'),
),
'fact-raw.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('fact-raw.sql'),
),
'ponder.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ponder.sql')
),
'policy-project.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('policy-project.sql'),
),
'daemonstatuskey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('daemonstatuskey.sql'),
),
'edgetype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('edgetype.sql'),
),
'ponder-comments.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ponder-comments.sql'),
),
'pastepolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('pastepolicy.sql'),
),
'xhprof.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('xhprof.sql'),
),
'draft-metadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('draft-metadata.sql'),
),
'phamedomain.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phamedomain.sql'),
),
'ponder-mailkey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('ponder-mailkey.sql'),
),
'ponder-mailkey-populate.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('ponder-mailkey-populate.php'),
),
'phamepolicy.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phamepolicy.sql'),
),
'phameoneblog.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('phameoneblog.sql'),
),
'statustxt.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('statustxt.sql'),
),
'daemontaskarchive.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('daemontaskarchive.sql'),
),
'drydocktaskid.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('drydocktaskid.sql'),
),
'drydockresoucetype.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('drydockresourcetype.sql'),
),
'liskcounters.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('liskcounters.sql'),
),
'liskcounters.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('liskcounters.php'),
),
'dropfileproxyimage.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('dropfileproxyimage.sql'),
),
'repository-lint.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('repository-lint.sql'),
),
'liskcounters-task.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('liskcounters-task.sql'),
),
'pholio.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('pholio.sql'),
),
'owners-exclude.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('owners-exclude.sql'),
),
'20121209.pholioxactions.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121209.pholioxactions.sql'),
),
'20121209.xmacroadd.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121209.xmacroadd.sql'),
),
'20121209.xmacromigrate.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20121209.xmacromigrate.php'),
),
'20121209.xmacromigratekey.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121209.xmacromigratekey.sql'),
),
'20121220.generalcache.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121220.generalcache.sql'),
),
'db.config' => array(
'type' => 'db',
'name' => 'config',
),
'20121226.config.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20121226.config.sql'),
),
'20130101.confxaction.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130101.confxaction.sql'),
),
'20130102.metamtareceivedmailmessageidhash.sql' => array(
'type' => 'sql',
'name' =>
$this->getPatchPath('20130102.metamtareceivedmailmessageidhash.sql'),
),
'20130103.filemetadata.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130103.filemetadata.sql'),
),
'20130111.conpherence.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130111.conpherence.sql'),
),
'20130127.altheraldtranscript.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130127.altheraldtranscript.sql'),
),
'20130201.revisionunsubscribed.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20130201.revisionunsubscribed.php'),
),
'20130201.revisionunsubscribed.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20130201.revisionunsubscribed.sql'),
),
+ '20130131.conpherencepics.sql' => array(
+ 'type' => 'sql',
+ 'name' => $this->getPatchPath('20130131.conpherencepics.sql'),
+ ),
);
}
}
diff --git a/src/view/form/control/AphrontFormCropControl.php b/src/view/form/control/AphrontFormCropControl.php
new file mode 100644
index 0000000000..26cb70c0e4
--- /dev/null
+++ b/src/view/form/control/AphrontFormCropControl.php
@@ -0,0 +1,99 @@
+<?php
+
+final class AphrontFormCropControl extends AphrontFormControl {
+
+ private $width = 50;
+ private $height = 50;
+
+ public function setHeight($height) {
+ $this->height = $height;
+ return $this;
+ }
+ public function getHeight() {
+ return $this->height;
+ }
+
+ public function setWidth($width) {
+ $this->width = $width;
+ return $this;
+ }
+ public function getWidth() {
+ return $this->width;
+ }
+
+ protected function getCustomControlClass() {
+ return 'aphront-form-crop';
+ }
+
+ protected function renderInput() {
+ $file = $this->getValue();
+
+ if ($file === null) {
+ return phutil_render_tag(
+ 'img',
+ array(
+ 'src' => PhabricatorUser::getDefaultProfileImageURI()
+ ),
+ ''
+ );
+ }
+
+ $c_id = celerity_generate_unique_node_id();
+ $metadata = $file->getMetadata();
+ $scale = PhabricatorImageTransformer::getScaleForCrop(
+ $file,
+ $this->getWidth(),
+ $this->getHeight()
+ );
+
+ Javelin::initBehavior(
+ 'aphront-crop',
+ array(
+ 'cropBoxID' => $c_id,
+ 'width' => $this->getWidth(),
+ 'height' => $this->getHeight(),
+ 'scale' => $scale,
+ 'imageH' => $metadata[PhabricatorFile::METADATA_IMAGE_HEIGHT],
+ 'imageW' => $metadata[PhabricatorFile::METADATA_IMAGE_WIDTH],
+ )
+ );
+
+ return javelin_render_tag(
+ 'div',
+ array(
+ 'id' => $c_id,
+ 'sigil' => 'crop-box',
+ 'mustcapture' => true,
+ 'class' => 'crop-box'
+ ),
+ javelin_render_tag(
+ 'img',
+ array(
+ 'src' => $file->getBestURI(),
+ 'class' => 'crop-image',
+ 'sigil' => 'crop-image'
+ ),
+ ''
+ ).
+ javelin_render_tag(
+ 'input',
+ array(
+ 'type' => 'hidden',
+ 'name' => 'image_x',
+ 'sigil' => 'crop-x',
+ ),
+ ''
+ ).
+ javelin_render_tag(
+ 'input',
+ array(
+ 'type' => 'hidden',
+ 'name' => 'image_y',
+ 'sigil' => 'crop-y',
+ ),
+ ''
+ )
+ );
+ }
+
+}
diff --git a/src/view/layout/PhabricatorMenuView.php b/src/view/layout/PhabricatorMenuView.php
index c863f9dfa1..c3a27a173a 100644
--- a/src/view/layout/PhabricatorMenuView.php
+++ b/src/view/layout/PhabricatorMenuView.php
@@ -1,164 +1,172 @@
<?php
final class PhabricatorMenuView extends AphrontTagView {
private $items = array();
protected function canAppendChild() {
return false;
}
- public function newLabel($name) {
+ public function newLabel($name, $key = null) {
$item = id(new PhabricatorMenuItemView())
->setType(PhabricatorMenuItemView::TYPE_LABEL)
->setName($name);
+ if ($key !== null) {
+ $item->setKey($key);
+ }
+
$this->addMenuItem($item);
return $item;
}
- public function newLink($name, $href) {
+ public function newLink($name, $href, $key = null) {
$item = id(new PhabricatorMenuItemView())
->setType(PhabricatorMenuItemView::TYPE_LINK)
->setName($name)
->setHref($href);
+ if ($key !== null) {
+ $item->setKey($key);
+ }
+
$this->addMenuItem($item);
return $item;
}
public function newButton($name, $href) {
$item = id(new PhabricatorMenuItemView())
->setType(PhabricatorMenuItemView::TYPE_BUTTON)
->setName($name)
->setHref($href);
$this->addMenuItem($item);
return $item;
}
public function addMenuItem(PhabricatorMenuItemView $item) {
return $this->addMenuItemAfter(null, $item);
}
public function addMenuItemAfter($key, PhabricatorMenuItemView $item) {
if ($key === null) {
$this->items[] = $item;
return $this;
}
if (!$this->getItem($key)) {
throw new Exception("No such key '{$key}' to add menu item after!");
}
$result = array();
foreach ($this->items as $other) {
$result[] = $other;
if ($other->getKey() == $key) {
$result[] = $item;
}
}
$this->items = $result;
return $this;
}
public function addMenuItemBefore($key, PhabricatorMenuItemView $item) {
if ($key === null) {
array_unshift($this->items, $item);
return $this;
}
$this->requireKey($key);
$result = array();
foreach ($this->items as $other) {
if ($other->getKey() == $key) {
$result[] = $item;
}
$result[] = $other;
}
$this->items = $result;
return $this;
}
public function addMenuItemToLabel($key, PhabricatorMenuItemView $item) {
$this->requireKey($key);
$other = $this->getItem($key);
if ($other->getType() != PhabricatorMenuItemView::TYPE_LABEL) {
throw new Exception("Menu item '{$key}' is not a label!");
}
$seen = false;
$after = null;
foreach ($this->items as $other) {
if (!$seen) {
if ($other->getKey() == $key) {
$seen = true;
}
} else {
if ($other->getType() == PhabricatorMenuItemView::TYPE_LABEL) {
break;
}
}
$after = $other->getKey();
}
return $this->addMenuItemAfter($after, $item);
}
private function requireKey($key) {
if (!$this->getItem($key)) {
throw new Exception("No menu item with key '{$key}' exists!");
}
}
public function getItem($key) {
$key = (string)$key;
// NOTE: We could optimize this, but need to update any map when items have
// their keys change. Since that's moderately complex, wait for a profile
// or use case.
foreach ($this->items as $item) {
if ($item->getKey() == $key) {
return $item;
}
}
return null;
}
public function getItems() {
return $this->items;
}
protected function willRender() {
$key_map = array();
foreach ($this->items as $item) {
$key = $item->getKey();
if ($key !== null) {
if (isset($key_map[$key])) {
throw new Exception(
"Menu contains duplicate items with key '{$key}'!");
}
$key_map[$key] = $item;
}
}
}
protected function getTagAttributes() {
return array(
'class' => 'phabricator-menu-view',
);
}
protected function getTagContent() {
return $this->renderHTMLView($this->items);
}
}
diff --git a/webroot/rsrc/css/aphront/form-view.css b/webroot/rsrc/css/aphront/form-view.css
index 52dc73e307..abca6a6b2d 100644
--- a/webroot/rsrc/css/aphront/form-view.css
+++ b/webroot/rsrc/css/aphront/form-view.css
@@ -1,353 +1,365 @@
/**
* @provides aphront-form-view-css
*/
/**
* These styles are overrides for .aphront-form-view
*/
.aphront-form-view-shaded {
border: 1px solid #d4dae0;
background: #f4f5f8;
}
.aphront-form-view-padded {
padding: 1em;
}
.aphront-form-view label.aphront-form-label {
padding-top: 4px;
width: 19%;
float: left;
text-align: right;
font-weight: bold;
font-size: 13px;
color: #666666;
}
.device-phone .aphront-form-view label.aphront-form-label {
display: block;
float: none;
text-align: left;
width: 100%;
}
.aphront-form-input {
margin-left: 20%;
margin-right: 25%;
width: 55%;
}
.device-phone .aphront-form-input {
margin-left: 0%;
margin-right: 0%;
width: 100%;
}
.aphront-form-control-text .aphront-form-input input,
.aphront-form-control-password .aphront-form-input input {
font-size: 13px;
padding: 4px 4px;
color: #333;
vertical-align: middle;
background-color: #ffffff;
border: 1px solid #96A6C5;
border-radius: 3px;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}
.aphront-form-error {
width: 23%;
float: right;
color: #aa0000;
font-weight: bold;
padding-top: 4px;
}
.device-phone .aphront-form-error {
float: none;
width: 100%;
}
.device-phone .aphront-form-drag-and-drop-upload {
display: none;
}
.aphront-form-required {
font-weight: normal;
color: #888888;
font-size: 11px;
}
.aphront-form-input input,
.aphront-form-input textarea {
font-size: 13px;
display: block;
width: 100%;
box-sizing: border-box;
}
.aphront-form-input textarea {
height: 12em;
}
.aphront-form-control {
padding: 4px;
}
.aphront-form-control-submit button,
.aphront-form-control-submit a.button {
float: right;
margin: 0.5em 0 0em 2%;
}
.aphront-form-control-textarea textarea.aphront-textarea-very-short {
height: 3em;
border: 1px solid #96A6C5;
border-radius: 3px;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
}
.aphront-form-control-textarea textarea.aphront-textarea-very-tall {
height: 24em;
}
.aphront-form-control-select .aphront-form-input {
padding-top: 2px;
}
.aphront-form-view .aphront-form-caption {
font-size: 12px;
color: #888;
padding: 2px;
text-align: right;
margin-right: 25%;
margin-left: 20%;
}
.device-phone .aphront-form-view .aphront-form-caption {
margin-right: 0%;
}
/* override for when inside an aphront-panel-view */
.aphront-panel-view .aphront-form-view h1 {
padding: 0em 0em .8em 0em;
}
.aphront-form-instructions {
margin: 0.75em 3% 1.25em;
}
.aphront-form-important {
margin: .5em 0;
background: #ffffdd;
padding: .5em 1em;
}
.aphront-form-important code {
display: block;
padding: .25em;
margin: .5em 2em;
}
.aphront-form-control-static .aphront-form-input,
.aphront-form-control-markup .aphront-form-input {
padding-top: 4px;
font-size: 13px;
}
.aphront-form-control-togglebuttons .aphront-form-input {
padding-top: 5px;
}
table.aphront-form-control-radio-layout,
table.aphront-form-control-checkbox-layout {
margin-top: 3px;
font-size: 13px;
}
table.aphront-form-control-radio-layout th,
table.aphront-form-control-checkbox-layout th {
padding-top: 2px;
padding-left: 0.35em;
padding-bottom: 4px;
}
.aphront-form-control-radio-layout td input,
.aphront-form-control-checkbox-layout td input {
margin-top: 4px;
width: auto;
}
.aphront-form-radio-caption {
font-size: 11px;
color: #444444;
max-width: 400px;
}
.aphront-form-control-image span {
margin: 0px 4px 0px 2px;
}
.aphront-form-control-image .default-image {
display: inline;
width: 12px;
}
.aphront-form-input hr {
border: none;
background: #bbbbbb;
height: 1px;
position: relative;
}
.aphront-form-inset {
margin: 0 0 1em;
padding: .75em;
background: #f3f3f3;
border: 1px solid #afafaf;
}
.aphront-form-drag-and-drop-file-list {
width: 400px;
}
.drag-and-drop-instructions {
color: #333333;
font-size: 11px;
padding: 6px 8px;
}
.drag-and-drop-file-target {
border: 1px dashed #bfbfbf;
padding-top: 10px;
padding-bottom: 10px;
}
.aphront-textarea-drag-and-drop {
background: #99ff99;
border-color: #669966;
}
+.aphront-form-crop .crop-box {
+ cursor: move;
+ overflow: hidden;
+}
+
+.aphront-form-crop .crop-box .crop-image {
+ position: relative;
+ top: 0px;
+ left: 0px;
+}
+
+
.calendar-button {
display: inline;
background: url(/rsrc/image/icon/fatcow/calendar_edit.png)
no-repeat center center;
padding: 8px 12px;
margin: 2px 8px 2px 2px;
position: relative;
border: 1px solid transparent;
}
.aphront-form-date-container {
position: relative;
display: inline;
}
.aphront-form-date-container select {
margin: 2px;
display: inline;
}
.aphront-form-date-container input.aphront-form-date-time-input {
width: 7em;
display: inline;
}
.fancy-datepicker {
position: absolute;
width: 240px;
}
.fancy-datepicker-core {
padding: 1px;
font-size: 11px;
font-family: Verdana;
text-align: center;
}
.fancy-datepicker-core .month-table,
.fancy-datepicker-core .day-table {
margin: 0 auto;
border-collapse: separate;
border-spacing: 1px;
width: 100%;
}
.fancy-datepicker-core .month-table {
margin-bottom: 6px;
}
.fancy-datepicker-core .month-table td.lrbutton {
width: 20%;
}
.fancy-datepicker-core .month-table td {
padding: 4px;
font-weight: bold;
color: #444444;
}
.fancy-datepicker-core .month-table td.lrbutton {
background: #e6e6e6;
border: 1px solid;
border-color: #a6a6a6 #969696 #868686 #a6a6a6;
}
.fancy-datepicker-core .day-table td {
overflow: hidden;
background: #f6f6f6;
vertical-align: center;
text-align: center;
border: 1px solid #d6d6d6;
padding: 4px 0;
}
.fancy-datepicker-core .day-table td.day-placeholder {
border-color: transparent;
background: transparent;
}
.fancy-datepicker-core .day-table td.weekend {
color: #666666;
border-color: #e6e6e6;
}
.fancy-datepicker-core .day-table td.day-name {
background: transparent;
border: 1px transparent;
vertical-align: bottom;
color: #888888;
}
.fancy-datepicker-core .day-table td.today {
background: #eeee99;
border-color: #aaaa66;
}
.fancy-datepicker-core .day-table td.datepicker-selected {
background: #0099ff;
border-color: #0066cc;
}
.fancy-datepicker-core td {
cursor: pointer;
}
.fancy-datepicker-core td.novalue {
cursor: inherit;
}
.picker-open .calendar-button,
.fancy-datepicker-core {
background-color: white;
border: 1px solid #777777;
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.25);
}
.picker-open .calendar-button {
border-left: 1px solid white;
}
diff --git a/webroot/rsrc/css/application/conpherence/header-pane.css b/webroot/rsrc/css/application/conpherence/header-pane.css
index d007091de3..27198a2879 100644
--- a/webroot/rsrc/css/application/conpherence/header-pane.css
+++ b/webroot/rsrc/css/application/conpherence/header-pane.css
@@ -1,50 +1,98 @@
/**
* @provides conpherence-header-pane-css
*/
#conpherence-main-pane {
position: relative;
}
.conpherence-header-pane {
border-bottom: 1px solid #ccc;
background: #fff;
height: 80px;
width: 100%;
}
.conpherence-header-pane .edit {
float: right;
margin: 16px 16px 0px 0px;
height: 50px;
width: 50px;
background-image: url('/rsrc/image/actions/edit.png');
}
.conpherence-header-pane .header-image {
position: absolute;
top: 15px;
left: 15px;
height: 50px;
width: 50px;
}
+.conpherence-header-pane .custom-header-image {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ height: 80px;
+ width: 120px;
+}
+
.conpherence-header-pane .title {
position: relative;
font-size: 16px;
font-weight: bold;
left: 77px;
top: 21px;
max-width: 80%;
overflow-x: auto;
}
+.conpherence-header-pane .custom-title {
+ position: relative;
+ font-size: 16px;
+ font-weight: bold;
+ left: 132px;
+ top: 21px;
+ max-width: 80%;
+ overflow-x: auto;
+}
+
.conpherence-header-pane .subtitle {
position: relative;
left: 77px;
top: 21px;
color: #bfbfbf;
max-width: 80%;
}
+.conpherence-header-pane .custom-subtitle {
+ position: relative;
+ left: 132px;
+ top: 21px;
+ color: #bfbfbf;
+ max-width: 80%;
+}
+
+.conpherence-header-pane .upload-photo {
+ display: none;
+}
+
+.conpherence-header-upload-photo .upload-photo {
+ display: block;
+ width: 100%;
+ padding: 32px;
+ font-size: 16px;
+ background: #99ff99;
+ border-color: #669966;
+}
+
+.conpherence-header-upload-photo .edit,
+.conpherence-header-upload-photo .header-image,
+.conpherence-header-upload-photo .custom-header-image,
+.conpherence-header-upload-photo .title,
+.conpherence-header-upload-photo .custom-title,
+.conpherence-header-upload-photo .subtitle,
+.conpherence-header-upload-photo .custom-subtitle {
+ display: none;
+}
diff --git a/webroot/rsrc/css/application/conpherence/update.css b/webroot/rsrc/css/application/conpherence/update.css
index fcf26c9674..bcd26fb4b4 100644
--- a/webroot/rsrc/css/application/conpherence/update.css
+++ b/webroot/rsrc/css/application/conpherence/update.css
@@ -1,7 +1,17 @@
/**
* @provides conpherence-update-css
*/
.phabricator-standard-page-body .aphront-dialog-view {
margin: 20px auto 0px auto;
}
+
+.aphront-dialog-view .conpherence-dialogue-drag-photo {
+ border: 1px dashed #bfbfbf;
+ padding: 10px 0px 10px 10px;
+}
+
+.aphront-dialog-view .conpherence-dialogue-upload-photo {
+ background: #99ff99;
+ border-color: #669966;
+}
diff --git a/webroot/rsrc/css/application/pholio/pholio.css b/webroot/rsrc/css/application/pholio/pholio.css
index 86031e9d5e..9a44602fb2 100644
--- a/webroot/rsrc/css/application/pholio/pholio.css
+++ b/webroot/rsrc/css/application/pholio/pholio.css
@@ -1,36 +1,45 @@
/**
* @provides pholio-css
*/
.pholio-mock-image-container {
background-color: #282828;
text-align: center;
}
.pholio-mock-carousel {
background-color: #282828;
text-align: center;
}
.pholio-mock-carousel-thumbnail {
margin-right: 5px;
display: inline-block;
cursor: pointer;
}
.pholio-mock-image {
display: inline-block;
}
-.pholio-mock-select {
- border: 1px solid #FF0000;
- position: absolute;
+.pholio-mock-select-border {
+ position: absolute;
+ background: #ffffff;
+ opacity: 0.25;
+ box-sizing: border-box;
+ border: 1px solid #000000;
+}
+
+.pholio-mock-select-fill {
+ position: absolute;
+ border: 1px dashed #ffffff;
+ box-sizing: border-box;
}
.pholio-mock-wrapper {
position: relative;
display: inline-block;
cursor: crosshair;
padding: 0px;
margin: 10px 0px;
}
diff --git a/webroot/rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js b/webroot/rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js
new file mode 100644
index 0000000000..a19bba029f
--- /dev/null
+++ b/webroot/rsrc/js/application/conpherence/behavior-drag-and-drop-photo.js
@@ -0,0 +1,39 @@
+/**
+ * @provides javelin-behavior-conpherence-drag-and-drop-photo
+ * @requires javelin-behavior
+ * javelin-dom
+ * javelin-workflow
+ * phabricator-drag-and-drop-file-upload
+ */
+
+JX.behavior('conpherence-drag-and-drop-photo', function(config) {
+
+ var target = JX.$(config.target);
+ var form_pane = JX.$(config.form_pane);
+
+ function onupload(f) {
+ var data = {
+ 'file_id' : f.getID(),
+ 'action' : 'metadata'
+ };
+
+ var form = JX.DOM.find(form_pane, 'form');
+ var workflow = JX.Workflow.newFromForm(form, data);
+ workflow.start();
+ }
+
+ if (JX.PhabricatorDragAndDropFileUpload.isSupported()) {
+ var drop = new JX.PhabricatorDragAndDropFileUpload(target)
+ .setURI(config.upload_uri);
+ drop.listen('didBeginDrag', function(e) {
+ JX.DOM.alterClass(target, config.activated_class, true);
+ });
+ drop.listen('didEndDrag', function(e) {
+ JX.DOM.alterClass(target, config.activated_class, false);
+ });
+ drop.listen('didUpload', onupload);
+ drop.start();
+ }
+
+});
+
diff --git a/webroot/rsrc/js/application/conpherence/behavior-menu.js b/webroot/rsrc/js/application/conpherence/behavior-menu.js
index 4ac216bdbf..64fcbd3130 100644
--- a/webroot/rsrc/js/application/conpherence/behavior-menu.js
+++ b/webroot/rsrc/js/application/conpherence/behavior-menu.js
@@ -1,96 +1,103 @@
/**
* @provides javelin-behavior-conpherence-menu
* @requires javelin-behavior
* javelin-dom
* javelin-workflow
* javelin-util
* javelin-stratcom
* javelin-uri
*/
JX.behavior('conpherence-menu', function(config) {
function onresponse(context, response) {
var header = JX.$H(response.header);
var messages = JX.$H(response.messages);
var form = JX.$H(response.form);
var widgets = JX.$H(response.widgets);
var headerRoot = JX.$(config.header);
var messagesRoot = JX.$(config.messages);
var formRoot = JX.$(config.form_pane);
var widgetsRoot = JX.$(config.widgets_pane);
+ var menuRoot = JX.$(config.menu_pane);
JX.DOM.setContent(headerRoot, header);
JX.DOM.setContent(messagesRoot, messages);
messagesRoot.scrollTop = messagesRoot.scrollHeight;
JX.DOM.setContent(formRoot, form);
JX.DOM.setContent(widgetsRoot, widgets);
- for (var i = 0; i < context.parentNode.childNodes.length; i++) {
- var current = context.parentNode.childNodes[i];
+ var conpherences = JX.DOM.scry(
+ menuRoot,
+ 'a',
+ 'conpherence-menu-click'
+ );
+
+ for (var i = 0; i < conpherences.length; i++) {
+ var current = conpherences[i];
if (current.id == context.id) {
JX.DOM.alterClass(current, 'conpherence-selected', true);
JX.DOM.alterClass(current, 'hide-unread-count', true);
} else {
JX.DOM.alterClass(current, 'conpherence-selected', false);
}
}
// TODO - update the browser URI T2086
JX.Stratcom.invoke(
'conpherence-selected-loaded',
null,
{}
);
}
JX.Stratcom.listen(
'click',
'conpherence-menu-click',
function(e) {
e.kill();
var selected = e.getNode(['conpherence-menu-click']);
if (config.fancy_ajax) {
JX.Stratcom.invoke(
'conpherence-selected',
null,
{ selected : selected }
);
} else {
var data = JX.Stratcom.getData(selected);
var uri = new JX.URI(config.base_uri + data.id + '/');
uri.go();
}
}
);
JX.Stratcom.listen(
'conpherence-initial-selected',
null,
function(e) {
var selected = e.getData().selected;
e.kill();
JX.Stratcom.invoke(
'conpherence-selected',
null,
{ selected : selected }
);
}
);
JX.Stratcom.listen(
'conpherence-selected',
null,
function(e) {
var selected = e.getData().selected;
var data = JX.Stratcom.getData(selected);
var uri = config.base_uri + 'view/' + data.id + '/';
new JX.Workflow(uri, {})
.setHandler(JX.bind(null, onresponse, selected))
.start();
}
);
});
diff --git a/webroot/rsrc/js/application/core/behavior-crop.js b/webroot/rsrc/js/application/core/behavior-crop.js
new file mode 100644
index 0000000000..965e3336f2
--- /dev/null
+++ b/webroot/rsrc/js/application/core/behavior-crop.js
@@ -0,0 +1,94 @@
+/**
+ * @provides javelin-behavior-aphront-crop
+ * @requires javelin-behavior
+ * javelin-dom
+ * javelin-vector
+ * javelin-magical-init
+ */
+
+ JX.behavior('aphront-crop', function(config) {
+
+ var dragging = false;
+ var startX, startY;
+ var finalX, finalY;
+ var dScale = config.scale;
+
+ var cropBox = JX.$(config.cropBoxID);
+ var basePos = JX.$V(cropBox);
+ cropBox.style.height = config.height + 'px';
+ cropBox.style.width = config.width + 'px';
+ var baseD = JX.$V(config.width, config.height);
+
+ var image = JX.DOM.find(cropBox, 'img', 'crop-image');
+ image.style.height = (config.imageH * config.scale) + 'px';
+ image.style.width = (config.imageW * config.scale) + 'px';
+ var imageD = JX.$V(
+ config.imageW * config.scale,
+ config.imageH * config.scale
+ );
+ var minLeft = baseD.x - imageD.x;
+ var minTop = baseD.y - imageD.y;
+
+ var minScale = Math.min(
+ config.width / config.imageW,
+ config.height / config.imageH,
+ 1
+ );
+ var maxScale = Math.max(
+ config.imageW / config.width,
+ config.imageH / config.height,
+ 2
+ );
+
+ var ondrag = function(e) {
+ e.kill();
+ dragging = true;
+ var p = JX.$V(e);
+ startX = p.x;
+ startY = p.y;
+ };
+
+ var onmove = function(e) {
+ if (!dragging) {
+ return;
+ }
+ e.kill();
+
+ var p = JX.$V(e);
+ var dx = startX - p.x;
+ var dy = startY - p.y;
+ var imagePos = JX.$V(image);
+ var moveLeft = imagePos.x - basePos.x - dx;
+ var moveTop = imagePos.y - basePos.y - dy;
+
+ image.style.left = Math.min(Math.max(minLeft, moveLeft), 0) + 'px';
+ image.style.top = Math.min(Math.max(minTop, moveTop), 0) + 'px';
+
+ // reset these; a new beginning!
+ startX = p.x;
+ startY = p.y;
+
+ // save off where we are right now
+ imagePos = JX.$V(image);
+ finalX = Math.abs(imagePos.x - basePos.x);
+ finalY = Math.abs(imagePos.y - basePos.y);
+ JX.DOM.find(cropBox, 'input', 'crop-x').value = finalX;
+ JX.DOM.find(cropBox, 'input', 'crop-y').value = finalY;
+ };
+
+ var ondrop = function(e) {
+ if (!dragging) {
+ return;
+ }
+ dragging = false;
+ };
+
+ // NOTE: Javelin does not dispatch mousemove by default.
+ JX.enableDispatch(cropBox, 'mousemove');
+
+ JX.DOM.listen(cropBox, 'mousedown', [], ondrag);
+ JX.DOM.listen(cropBox, 'mousemove', [], onmove);
+ JX.DOM.listen(cropBox, 'mouseup', [], ondrop);
+ JX.DOM.listen(cropBox, 'mouseout', [], ondrop);
+
+});
diff --git a/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js b/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js
index d9c438eb80..7b0e0fb1d1 100644
--- a/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js
+++ b/webroot/rsrc/js/application/pholio/behavior-pholio-mock-view.js
@@ -1,127 +1,150 @@
/**
* @provides javelin-behavior-pholio-mock-view
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
* javelin-vector
- * javelin-event
+ * javelin-magical-init
+ * javelin-request
*/
JX.behavior('pholio-mock-view', function(config) {
var is_dragging = false;
var wrapper = JX.$('mock-wrapper');
var image;
var imageData;
var startPos;
var endPos;
- var selection;
+
+ var selection_border;
+ var selection_fill;
JX.Stratcom.listen(
'click', // Listen for clicks...
'mock-thumbnail', // ...on nodes with sigil "mock-thumbnail".
function(e) {
var data = e.getNodeData('mock-thumbnail');
var main = JX.$(config.mainID);
JX.Stratcom.addData(
main,
{
fullSizeURI: data['fullSizeURI'],
imageID: data['imageID']
});
main.src = data.fullSizeURI;
JX.DOM.setContent(wrapper,main);
});
- function draw_rectangle(node, current, init) {
- JX.$V(
- Math.abs(current.x-init.x),
- Math.abs(current.y-init.y))
- .setDim(node);
+ function draw_rectangle(nodes, current, init) {
+ for (var ii = 0; ii < nodes.length; ii++) {
+ var node = nodes[ii];
+
+ JX.$V(
+ Math.abs(current.x-init.x),
+ Math.abs(current.y-init.y))
+ .setDim(node);
- JX.$V(
- (current.x-init.x < 0) ? current.x:init.x,
- (current.y-init.y < 0) ? current.y:init.y)
- .setPos(node);
+ JX.$V(
+ (current.x-init.x < 0) ? current.x:init.x,
+ (current.y-init.y < 0) ? current.y:init.y)
+ .setPos(node);
+ }
}
function getRealXY(parent, point) {
var pos = {x: (point.x - parent.x), y: (point.y - parent.y)};
+ var dim = JX.Vector.getDim(image);
- if (pos.x < 0) pos.x = 0;
- else if (pos.x > image.clientWidth) pos.x = image.clientWidth - 1;
-
- if (pos.y < 0) pos.y = 0;
- else if (pos.y > image.clientHeight) pos.y = image.clientHeight - 2;
+ pos.x = Math.max(0, Math.min(pos.x, dim.x));
+ pos.y = Math.max(0, Math.min(pos.y, dim.y));
return pos;
}
JX.Stratcom.listen('mousedown', 'mock-wrapper', function(e) {
if (!e.isNormalMouseEvent()) {
return;
}
image = JX.$(config.mainID);
imageData = JX.Stratcom.getData(image);
e.getRawEvent().target.draggable = false;
is_dragging = true;
startPos = getRealXY(JX.$V(wrapper),JX.$V(e));
- selection = JX.$N(
+ selection_border = JX.$N(
'div',
- {className: 'pholio-mock-select'}
- );
-
-
- JX.$V(startPos.x,startPos.y).setPos(selection);
+ {className: 'pholio-mock-select-border'});
- JX.DOM.appendContent(wrapper, selection);
+ selection_fill = JX.$N(
+ 'div',
+ {className: 'pholio-mock-select-fill'});
+ JX.$V(startPos.x, startPos.y).setPos(selection_border);
+ JX.$V(startPos.x, startPos.y).setPos(selection_fill);
+ JX.DOM.appendContent(wrapper, [selection_border, selection_fill]);
});
JX.enableDispatch(document.body, 'mousemove');
JX.Stratcom.listen('mousemove',null, function(e) {
if (!is_dragging) {
return;
}
- draw_rectangle(selection, getRealXY(JX.$V(wrapper), JX.$V(e)), startPos);
+ draw_rectangle(
+ [selection_border, selection_fill],
+ getRealXY(JX.$V(wrapper),
+ JX.$V(e)), startPos);
});
JX.Stratcom.listen(
'mouseup',
null,
function(e) {
if (!is_dragging) {
return;
}
is_dragging = false;
endPos = getRealXY(JX.$V(wrapper), JX.$V(e));
comment = window.prompt("Add your comment");
if (comment == null || comment == "") {
- selection.remove();
+ JX.DOM.remove(selection_border);
+ JX.DOM.remove(selection_fill);
return;
}
- selection.title = comment;
+ selection_fill.title = comment;
+
+ var saveURL = "/pholio/inline/" + imageData['imageID'] + "/";
+
+ var inlineComment = new JX.Request(saveURL, function(r) {
+
+ });
+
+ var commentToAdd = {
+ mockID: config.mockID,
+ imageID: imageData['imageID'],
+ startX: Math.min(startPos.x, endPos.x),
+ startY: Math.min(startPos.y, endPos.y),
+ endX: Math.max(startPos.x,endPos.x),
+ endY: Math.max(startPos.y,endPos.y),
+ comment: comment};
+
- console.log("ImageID: " + imageData['imageID'] +
- ", coords: (" + Math.min(startPos.x, endPos.x) + "," +
- Math.min(startPos.y, endPos.y) + ") -> (" +
- Math.max(startPos.x,endPos.x) + "," + Math.max(startPos.y,endPos.y) +
- "), comment: " + comment);
+ inlineComment.addData(commentToAdd);
+ inlineComment.send();
});
});

File Metadata

Mime Type
text/x-diff
Expires
Sun, Nov 16, 10:35 AM (48 m, 55 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
338903
Default Alt Text
(776 KB)

Event Timeline