mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 14:00:56 +01:00
Merge branch 'master' of github.com:facebook/phabricator into new
This commit is contained in:
commit
81e3ec5998
182 changed files with 3141 additions and 566 deletions
|
@ -12,6 +12,7 @@
|
|||
"diffusion" : "Diffusion (Repository Browser)",
|
||||
"maniphest" : "Maniphest (Task Tracking)",
|
||||
"herald" : "Herald (Notifications)",
|
||||
"conduit" : "Conduit (Phabricator HTTP API)",
|
||||
"celerity" : "Celerity (CSS/JS Management)",
|
||||
"aphront" : "Aphront (Web Stack)",
|
||||
"console" : "DarkConsole (Debugging Console)",
|
||||
|
|
|
@ -2,6 +2,11 @@ This is not a complete list of changes, just of API or workflow changes that may
|
|||
break existing installs. Newer changes are listed at the top. If you pull new
|
||||
changes and things stop working, check here first!
|
||||
|
||||
June 29 2011 - Maniphest project indexes
|
||||
Old Maniphest tasks will not appear in project filter views until you run
|
||||
"scripts/search/reindex_maniphest.php" to build indexes. New tasks will have
|
||||
their indexes built automatically.
|
||||
|
||||
May 31 2011 - Javelin submodule moved
|
||||
The externals/javelin submodule location has moved. If you have an older
|
||||
checkout of Phabricator, you may need to edit .git/config to point at
|
||||
|
|
|
@ -190,6 +190,27 @@ return array(
|
|||
// Prefix prepended to mail sent by Differential.
|
||||
'metamta.differential.subject-prefix' => '[Differential]',
|
||||
|
||||
// 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,
|
||||
|
||||
|
||||
// -- Auth ------------------------------------------------------------------ //
|
||||
|
||||
|
@ -294,14 +315,6 @@ return array(
|
|||
// behalf, silencing the warning.
|
||||
'phabricator.timezone' => null,
|
||||
|
||||
|
||||
// Phabricator can highlight PHP by default, but if you want syntax
|
||||
// highlighting for other languages you should 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,
|
||||
|
||||
|
||||
// -- Files ----------------------------------------------------------------- //
|
||||
|
||||
// Lists which uploaded file types may be viewed in the browser. If a file
|
||||
|
@ -372,6 +385,37 @@ return array(
|
|||
// silly (but sort of awesome).
|
||||
'remarkup.enable-embedded-youtube' => false,
|
||||
|
||||
|
||||
// -- 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.
|
||||
|
||||
// Since the GC daemon can issue large writes and table scans, you may want to
|
||||
// run it only during off hours or make sure it is scheduled so it doesn't
|
||||
// overlap with backups. This determines when the daemon can start running
|
||||
// each day.
|
||||
'gcdaemon.run-at' => '12 AM',
|
||||
|
||||
// How many seconds after 'gcdaemon.run-at' the daemon may collect garbage
|
||||
// for. By default it runs continuously, but you can set it to run for a
|
||||
// limited period of time. For instance, if you do backups at 3 AM, you might
|
||||
// run garbage collection for an hour beforehand. This is not a high-precision
|
||||
// limit so you may want to leave some room for the GC to actually stop, and
|
||||
// if you set it to something like 3 seconds you're on your own.
|
||||
'gcdaemon.run-for' => 24 * 60 * 60,
|
||||
|
||||
// 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-render-cache' => 7 * (24 * 60 * 60),
|
||||
|
||||
|
||||
// -- Customization --------------------------------------------------------- //
|
||||
|
||||
// Paths to additional phutil libraries to load.
|
||||
|
@ -405,4 +449,60 @@ return array(
|
|||
// settings are the defaults.)
|
||||
'celerity.force-disk-reads' => false,
|
||||
|
||||
// -- Pygments ------------------------------------------------------------ //
|
||||
// Phabricator can highlight PHP by default, but if you want syntax
|
||||
// highlighting for other languages you should 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',
|
||||
'diff' => 'Diff',
|
||||
'django' => 'Django Templating',
|
||||
'erb' => 'Embedded Ruby/ERB',
|
||||
'erlang' => 'Erlang',
|
||||
'html' => 'HTML',
|
||||
'infer' => 'Infer from title (extension)',
|
||||
'java' => 'Java',
|
||||
'js' => 'Javascript',
|
||||
'mysql' => 'MySQL',
|
||||
'perl' => 'Perl',
|
||||
'php' => 'PHP',
|
||||
'text' => 'Plain Text',
|
||||
'python' => 'Python',
|
||||
// TODO: 'remarkup' => 'Remarkup',
|
||||
'ruby' => 'Ruby',
|
||||
'xml' => 'XML',
|
||||
),
|
||||
|
||||
'pygments.dropdown-default' => 'infer',
|
||||
|
||||
// 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,
|
||||
),
|
||||
|
||||
);
|
||||
|
|
2
externals/javelin
vendored
2
externals/javelin
vendored
|
@ -1 +1 @@
|
|||
Subproject commit c727216edfb2527d14e1047656986f0cb8f694f9
|
||||
Subproject commit c6bf95cd19da7179c10220a858f4662139b6c3a0
|
6
resources/sql/patches/051.projectfilter.sql
Normal file
6
resources/sql/patches/051.projectfilter.sql
Normal file
|
@ -0,0 +1,6 @@
|
|||
CREATE TABLE phabricator_maniphest.maniphest_taskproject (
|
||||
taskPHID varchar(64) BINARY NOT NULL,
|
||||
projectPHID varchar(64) BINARY NOT NULL,
|
||||
PRIMARY KEY (projectPHID, taskPHID),
|
||||
UNIQUE KEY (taskPHID, projectPHID)
|
||||
);
|
2
resources/sql/patches/052.pastelanguage.sql
Normal file
2
resources/sql/patches/052.pastelanguage.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE phabricator_pastebin.pastebin_paste
|
||||
ADD COLUMN language VARCHAR(64) NOT NULL;
|
21
resources/sql/patches/053.feed.sql
Normal file
21
resources/sql/patches/053.feed.sql
Normal file
|
@ -0,0 +1,21 @@
|
|||
CREATE DATABASE phabricator_feed;
|
||||
|
||||
CREATE TABLE phabricator_feed.feed_storydata (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARCHAR(64) BINARY NOT NULL,
|
||||
UNIQUE KEY (phid),
|
||||
chronologicalKey BIGINT UNSIGNED NOT NULL,
|
||||
UNIQUE KEY (chronologicalKey),
|
||||
storyType varchar(64) NOT NULL,
|
||||
storyData LONGBLOB NOT NULL,
|
||||
authorPHID varchar(64) BINARY NOT NULL,
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE phabricator_feed.feed_storyreference (
|
||||
objectPHID varchar(64) BINARY NOT NULL,
|
||||
chronologicalKey BIGINT UNSIGNED NOT NULL,
|
||||
UNIQUE KEY (objectPHID, chronologicalKey),
|
||||
KEY (chronologicalKey)
|
||||
);
|
6
resources/sql/patches/054.subscribers.sql
Normal file
6
resources/sql/patches/054.subscribers.sql
Normal file
|
@ -0,0 +1,6 @@
|
|||
CREATE TABLE phabricator_maniphest.maniphest_tasksubscriber (
|
||||
taskPHID varchar(64) BINARY NOT NULL,
|
||||
subscriberPHID varchar(64) BINARY NOT NULL,
|
||||
PRIMARY KEY (subscriberPHID, taskPHID),
|
||||
UNIQUE KEY (taskPHID, subscriberPHID)
|
||||
);
|
|
@ -65,10 +65,10 @@ then
|
|||
# (it tries to pull in php 5.1 stuff) ...
|
||||
echo "Adding EPEL repo, for git."
|
||||
$SUDO rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
|
||||
YUMCOMMAND="$SUDO yum install httpd git php53 php53-cli php53-mysql php53-process php53-devel php53-gd gcc wget make pcre-devel"
|
||||
YUMCOMMAND="$SUDO yum install httpd git php53 php53-cli php53-mysql php53-process php53-devel php53-gd gcc wget make pcre-devel mysql-server"
|
||||
else
|
||||
# RHEL 6+ defaults with php 5.3
|
||||
YUMCOMMAND="$SUDO yum install httpd git php php-cli php-mysql php-process php-devel php-gd php-pecl-apc php-pecl-json"
|
||||
YUMCOMMAND="$SUDO yum install httpd git php php-cli php-mysql php-process php-devel php-gd php-pecl-apc php-pecl-json mysql-server"
|
||||
fi
|
||||
|
||||
echo "Dropping to yum to install dependencies..."
|
||||
|
|
63
scripts/install/update_phabricator.sh
Executable file
63
scripts/install/update_phabricator.sh
Executable file
|
@ -0,0 +1,63 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
# This is an example script for updating Phabricator, similar to the one used to
|
||||
# update <https://secure.phabricator.com/>. It might not work perfectly on your
|
||||
# system, but hopefully it should be easy to adapt.
|
||||
|
||||
# NOTE: This script assumes you are running it from a directory which contains
|
||||
# arcanist/, libphutil/, phabricator/, and possibly diviner/.
|
||||
|
||||
ROOT=`pwd` # You can hard-code the path here instead.
|
||||
|
||||
|
||||
### UPDATE WORKING COPIES ######################################################
|
||||
|
||||
if [ -e $ROOT/diviner ]
|
||||
then
|
||||
(cd $ROOT/diviner && git pull)
|
||||
fi
|
||||
|
||||
(cd $ROOT/libphutil && git pull)
|
||||
(cd $ROOT/arcanist && git pull)
|
||||
(cd $ROOT/phabricator && git pull && git submodule update --init)
|
||||
|
||||
|
||||
### GENERATE DOCUMENTATION #####################################################
|
||||
|
||||
# This generates documentation if you have diviner/ checked out. You generally
|
||||
# don't need to do this unless you're contributing to Phabricator and want to
|
||||
# preview some of the amazing documentation you've just written.
|
||||
if [ -e $ROOT/diviner ]
|
||||
then
|
||||
(cd $ROOT/diviner && $ROOT/diviner/bin/diviner .)
|
||||
(cd $ROOT/libphutil && $ROOT/diviner/bin/diviner .)
|
||||
(cd $ROOT/arcanist && $ROOT/diviner/bin/diviner .)
|
||||
(cd $ROOT/phabricator && $ROOT/diviner/bin/diviner .)
|
||||
fi
|
||||
|
||||
### CYCLE APACHE AND DAEMONS ###################################################
|
||||
|
||||
# Stop Apache. Depening on what system you're running, you may need to use
|
||||
# 'apachectl' or something else to cycle apache.
|
||||
sudo /etc/init.d/httpd stop
|
||||
|
||||
# Stop daemons.
|
||||
$ROOT/phabricator/bin/phd stop
|
||||
|
||||
# Upgrade the database schema.
|
||||
$ROOT/phabricator/scripts/sql/upgrade_schema.php -f
|
||||
|
||||
# Restart apache.
|
||||
sudo /etc/init.d/httpd start
|
||||
|
||||
# Restart daemons. Customize this to start whatever daemons you're running on
|
||||
# your system.
|
||||
|
||||
# $ROOT/phabricator/bin/phd repository-launch-master
|
||||
# $ROOT/phabricator/bin/phd launch metamta
|
||||
# $ROOT/phabricator/bin/phd launch garbagecollector
|
||||
# $ROOT/phabricator/bin/phd launch 4 taskmaster
|
||||
# $ROOT/phabricator/bin/phd launch ircbot /config/bot.json
|
33
scripts/search/reindex_maniphest.php
Executable file
33
scripts/search/reindex_maniphest.php
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
$root = dirname(dirname(dirname(__FILE__)));
|
||||
require_once $root.'/scripts/__init_script__.php';
|
||||
require_once $root.'/scripts/__init_env__.php';
|
||||
|
||||
ini_set('memory_limit', -1);
|
||||
$tasks = id(new ManiphestTask())->loadAll();
|
||||
echo "Updating relationships for ".count($tasks)." tasks";
|
||||
foreach ($tasks as $task) {
|
||||
ManiphestTaskProject::updateTaskProjects($task);
|
||||
ManiphestTaskSubscriber::updateTaskSubscribers($task);
|
||||
echo '.';
|
||||
}
|
||||
echo "\nDone.\n";
|
||||
|
|
@ -258,7 +258,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'herald-rule-editor' =>
|
||||
array(
|
||||
'uri' => '/res/402e94d2/rsrc/js/application/herald/HeraldRuleEditor.js',
|
||||
'uri' => '/res/ba957508/rsrc/js/application/herald/HeraldRuleEditor.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -285,17 +285,18 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
0 =>
|
||||
array(
|
||||
'uri' => '/res/39de799e/rsrc/js/javelin/docs/Base.js',
|
||||
'uri' => '/res/1da00bfe/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-install',
|
||||
0 => 'javelin-uri',
|
||||
1 => 'javelin-php-serializer',
|
||||
),
|
||||
'disk' => '/rsrc/js/javelin/docs/Base.js',
|
||||
'disk' => '/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
),
|
||||
'javelin-behavior' =>
|
||||
array(
|
||||
'uri' => '/res/3c772c64/rsrc/js/javelin/lib/behavior.js',
|
||||
'uri' => '/res/b28adfa1/rsrc/js/javelin/lib/behavior.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -613,7 +614,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-behavior-phabricator-keyboard-shortcuts' =>
|
||||
array(
|
||||
'uri' => '/res/7aed0604/rsrc/js/application/core/behavior-keyboard-shortcuts.js',
|
||||
'uri' => '/res/94b009e2/rsrc/js/application/core/behavior-keyboard-shortcuts.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -665,7 +666,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-dom' =>
|
||||
array(
|
||||
'uri' => '/res/43e9e2de/rsrc/js/javelin/lib/DOM.js',
|
||||
'uri' => '/res/34e7f2b5/rsrc/js/javelin/lib/DOM.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -689,7 +690,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-install' =>
|
||||
array(
|
||||
'uri' => '/res/f4d0e147/rsrc/js/javelin/core/install.js',
|
||||
'uri' => '/res/b6692f42/rsrc/js/javelin/core/install.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -700,7 +701,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-json' =>
|
||||
array(
|
||||
'uri' => '/res/1c4e3f6a/rsrc/js/javelin/lib/JSON.js',
|
||||
'uri' => '/res/f23dbfbd/rsrc/js/javelin/lib/JSON.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -711,7 +712,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-magical-init' =>
|
||||
array(
|
||||
'uri' => '/res/92e7f37e/rsrc/js/javelin/core/init.js',
|
||||
'uri' => '/res/6a069362/rsrc/js/javelin/core/init.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -732,7 +733,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-request' =>
|
||||
array(
|
||||
'uri' => '/res/1ed0d596/rsrc/js/javelin/lib/Request.js',
|
||||
'uri' => '/res/786bfe6f/rsrc/js/javelin/lib/Request.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -740,12 +741,13 @@ celerity_register_resource_map(array(
|
|||
1 => 'javelin-stratcom',
|
||||
2 => 'javelin-util',
|
||||
3 => 'javelin-behavior',
|
||||
4 => 'javelin-json',
|
||||
),
|
||||
'disk' => '/rsrc/js/javelin/lib/Request.js',
|
||||
),
|
||||
'javelin-stratcom' =>
|
||||
array(
|
||||
'uri' => '/res/9e7eb62b/rsrc/js/javelin/core/Stratcom.js',
|
||||
'uri' => '/res/d6cf4631/rsrc/js/javelin/core/Stratcom.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -758,7 +760,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-tokenizer' =>
|
||||
array(
|
||||
'uri' => '/res/83787676/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
|
||||
'uri' => '/res/c2dbba74/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -771,7 +773,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-typeahead' =>
|
||||
array(
|
||||
'uri' => '/res/ae18ee16/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
|
||||
'uri' => '/res/354d32f1/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -782,6 +784,18 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
|
||||
),
|
||||
'javelin-typeahead-composite-source' =>
|
||||
array(
|
||||
'uri' => '/res/9873d21c/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/a5d60e3c/rsrc/js/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js',
|
||||
|
@ -794,7 +808,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-typeahead-ondemand-source' =>
|
||||
array(
|
||||
'uri' => '/res/0015bbf5/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js',
|
||||
'uri' => '/res/b2e527e4/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -808,7 +822,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-typeahead-preloaded-source' =>
|
||||
array(
|
||||
'uri' => '/res/863a173c/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js',
|
||||
'uri' => '/res/f3c1e7c7/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -822,7 +836,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-typeahead-source' =>
|
||||
array(
|
||||
'uri' => '/res/58518dde/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadSource.js',
|
||||
'uri' => '/res/8a3aa262/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadSource.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -835,7 +849,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-uri' =>
|
||||
array(
|
||||
'uri' => '/res/70c9d32b/rsrc/js/javelin/lib/URI.js',
|
||||
'uri' => '/res/1c0ead43/rsrc/js/javelin/lib/URI.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -847,7 +861,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-util' =>
|
||||
array(
|
||||
'uri' => '/res/be43fdba/rsrc/js/javelin/core/util.js',
|
||||
'uri' => '/res/725cc90d/rsrc/js/javelin/core/util.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -856,7 +870,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-vector' =>
|
||||
array(
|
||||
'uri' => '/res/cd4721c4/rsrc/js/javelin/lib/Vector.js',
|
||||
'uri' => '/res/50535cb8/rsrc/js/javelin/lib/Vector.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -867,7 +881,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-workflow' =>
|
||||
array(
|
||||
'uri' => '/res/28a267b3/rsrc/js/javelin/lib/Workflow.js',
|
||||
'uri' => '/res/91a04640/rsrc/js/javelin/lib/Workflow.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -1066,7 +1080,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'phabricator-search-results-css' =>
|
||||
array(
|
||||
'uri' => '/res/9a9eeaf2/rsrc/css/application/search/search-results.css',
|
||||
'uri' => '/res/f8a86e27/rsrc/css/application/search/search-results.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -1125,7 +1139,7 @@ celerity_register_resource_map(array(
|
|||
'uri' => '/res/pkg/03ef179e/diffusion.pkg.css',
|
||||
'type' => 'css',
|
||||
),
|
||||
'2892314d' =>
|
||||
'25f94e94' =>
|
||||
array (
|
||||
'name' => 'typeahead.pkg.js',
|
||||
'symbols' =>
|
||||
|
@ -1138,7 +1152,26 @@ celerity_register_resource_map(array(
|
|||
5 => 'javelin-tokenizer',
|
||||
6 => 'javelin-behavior-aphront-basic-tokenizer',
|
||||
),
|
||||
'uri' => '/res/pkg/2892314d/typeahead.pkg.js',
|
||||
'uri' => '/res/pkg/25f94e94/typeahead.pkg.js',
|
||||
'type' => 'js',
|
||||
),
|
||||
'307df223' =>
|
||||
array (
|
||||
'name' => 'javelin.pkg.js',
|
||||
'symbols' =>
|
||||
array (
|
||||
0 => 'javelin-util',
|
||||
1 => 'javelin-install',
|
||||
2 => 'javelin-event',
|
||||
3 => 'javelin-stratcom',
|
||||
4 => 'javelin-behavior',
|
||||
5 => 'javelin-request',
|
||||
6 => 'javelin-vector',
|
||||
7 => 'javelin-dom',
|
||||
8 => 'javelin-json',
|
||||
9 => 'javelin-uri',
|
||||
),
|
||||
'uri' => '/res/pkg/307df223/javelin.pkg.js',
|
||||
'type' => 'js',
|
||||
),
|
||||
55967526 =>
|
||||
|
@ -1182,40 +1215,7 @@ celerity_register_resource_map(array(
|
|||
'uri' => '/res/pkg/8e9024dc/core.pkg.css',
|
||||
'type' => 'css',
|
||||
),
|
||||
'da416e1c' =>
|
||||
array (
|
||||
'name' => 'differential.pkg.js',
|
||||
'symbols' =>
|
||||
array (
|
||||
0 => 'javelin-behavior-differential-feedback-preview',
|
||||
1 => 'javelin-behavior-differential-edit-inline-comments',
|
||||
2 => 'javelin-behavior-differential-populate',
|
||||
3 => 'javelin-behavior-differential-show-more',
|
||||
4 => 'javelin-behavior-differential-diff-radios',
|
||||
),
|
||||
'uri' => '/res/pkg/da416e1c/differential.pkg.js',
|
||||
'type' => 'js',
|
||||
),
|
||||
'db95a6d0' =>
|
||||
array (
|
||||
'name' => 'javelin.pkg.js',
|
||||
'symbols' =>
|
||||
array (
|
||||
0 => 'javelin-util',
|
||||
1 => 'javelin-install',
|
||||
2 => 'javelin-event',
|
||||
3 => 'javelin-stratcom',
|
||||
4 => 'javelin-behavior',
|
||||
5 => 'javelin-request',
|
||||
6 => 'javelin-vector',
|
||||
7 => 'javelin-dom',
|
||||
8 => 'javelin-json',
|
||||
9 => 'javelin-uri',
|
||||
),
|
||||
'uri' => '/res/pkg/db95a6d0/javelin.pkg.js',
|
||||
'type' => 'js',
|
||||
),
|
||||
'f1d27e2a' =>
|
||||
'd0713563' =>
|
||||
array (
|
||||
'name' => 'workflow.pkg.js',
|
||||
'symbols' =>
|
||||
|
@ -1228,7 +1228,21 @@ celerity_register_resource_map(array(
|
|||
5 => 'phabricator-keyboard-shortcut',
|
||||
6 => 'javelin-behavior-phabricator-keyboard-shortcuts',
|
||||
),
|
||||
'uri' => '/res/pkg/f1d27e2a/workflow.pkg.js',
|
||||
'uri' => '/res/pkg/d0713563/workflow.pkg.js',
|
||||
'type' => 'js',
|
||||
),
|
||||
'da416e1c' =>
|
||||
array (
|
||||
'name' => 'differential.pkg.js',
|
||||
'symbols' =>
|
||||
array (
|
||||
0 => 'javelin-behavior-differential-feedback-preview',
|
||||
1 => 'javelin-behavior-differential-edit-inline-comments',
|
||||
2 => 'javelin-behavior-differential-populate',
|
||||
3 => 'javelin-behavior-differential-show-more',
|
||||
4 => 'javelin-behavior-differential-diff-radios',
|
||||
),
|
||||
'uri' => '/res/pkg/da416e1c/differential.pkg.js',
|
||||
'type' => 'js',
|
||||
),
|
||||
),
|
||||
|
@ -1252,38 +1266,38 @@ celerity_register_resource_map(array(
|
|||
'differential-revision-history-css' => '55967526',
|
||||
'differential-table-of-contents-css' => '55967526',
|
||||
'diffusion-commit-view-css' => '03ef179e',
|
||||
'javelin-behavior' => 'db95a6d0',
|
||||
'javelin-behavior-aphront-basic-tokenizer' => '2892314d',
|
||||
'javelin-behavior-aphront-form-disable-on-submit' => 'f1d27e2a',
|
||||
'javelin-behavior' => '307df223',
|
||||
'javelin-behavior-aphront-basic-tokenizer' => '25f94e94',
|
||||
'javelin-behavior-aphront-form-disable-on-submit' => 'd0713563',
|
||||
'javelin-behavior-differential-diff-radios' => 'da416e1c',
|
||||
'javelin-behavior-differential-edit-inline-comments' => 'da416e1c',
|
||||
'javelin-behavior-differential-feedback-preview' => 'da416e1c',
|
||||
'javelin-behavior-differential-populate' => 'da416e1c',
|
||||
'javelin-behavior-differential-show-more' => 'da416e1c',
|
||||
'javelin-behavior-phabricator-keyboard-shortcuts' => 'f1d27e2a',
|
||||
'javelin-behavior-workflow' => 'f1d27e2a',
|
||||
'javelin-dom' => 'db95a6d0',
|
||||
'javelin-event' => 'db95a6d0',
|
||||
'javelin-install' => 'db95a6d0',
|
||||
'javelin-json' => 'db95a6d0',
|
||||
'javelin-mask' => 'f1d27e2a',
|
||||
'javelin-request' => 'db95a6d0',
|
||||
'javelin-stratcom' => 'db95a6d0',
|
||||
'javelin-tokenizer' => '2892314d',
|
||||
'javelin-typeahead' => '2892314d',
|
||||
'javelin-typeahead-normalizer' => '2892314d',
|
||||
'javelin-typeahead-ondemand-source' => '2892314d',
|
||||
'javelin-typeahead-preloaded-source' => '2892314d',
|
||||
'javelin-typeahead-source' => '2892314d',
|
||||
'javelin-uri' => 'db95a6d0',
|
||||
'javelin-util' => 'db95a6d0',
|
||||
'javelin-vector' => 'db95a6d0',
|
||||
'javelin-workflow' => 'f1d27e2a',
|
||||
'javelin-behavior-phabricator-keyboard-shortcuts' => 'd0713563',
|
||||
'javelin-behavior-workflow' => 'd0713563',
|
||||
'javelin-dom' => '307df223',
|
||||
'javelin-event' => '307df223',
|
||||
'javelin-install' => '307df223',
|
||||
'javelin-json' => '307df223',
|
||||
'javelin-mask' => 'd0713563',
|
||||
'javelin-request' => '307df223',
|
||||
'javelin-stratcom' => '307df223',
|
||||
'javelin-tokenizer' => '25f94e94',
|
||||
'javelin-typeahead' => '25f94e94',
|
||||
'javelin-typeahead-normalizer' => '25f94e94',
|
||||
'javelin-typeahead-ondemand-source' => '25f94e94',
|
||||
'javelin-typeahead-preloaded-source' => '25f94e94',
|
||||
'javelin-typeahead-source' => '25f94e94',
|
||||
'javelin-uri' => '307df223',
|
||||
'javelin-util' => '307df223',
|
||||
'javelin-vector' => '307df223',
|
||||
'javelin-workflow' => 'd0713563',
|
||||
'phabricator-core-buttons-css' => '8e9024dc',
|
||||
'phabricator-core-css' => '8e9024dc',
|
||||
'phabricator-directory-css' => '8e9024dc',
|
||||
'phabricator-keyboard-shortcut' => 'f1d27e2a',
|
||||
'phabricator-keyboard-shortcut-manager' => 'f1d27e2a',
|
||||
'phabricator-keyboard-shortcut' => 'd0713563',
|
||||
'phabricator-keyboard-shortcut-manager' => 'd0713563',
|
||||
'phabricator-remarkup-css' => '8e9024dc',
|
||||
'phabricator-standard-page-view' => '8e9024dc',
|
||||
'syntax-highlighting-css' => '8e9024dc',
|
||||
|
|
|
@ -103,6 +103,7 @@ phutil_register_library_map(array(
|
|||
'ConduitAPI_differential_updateunitresults_Method' => 'applications/conduit/method/differential/updateunitresults',
|
||||
'ConduitAPI_diffusion_getcommits_Method' => 'applications/conduit/method/diffusion/getcommits',
|
||||
'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'applications/conduit/method/diffusion/getrecentcommitsbypath',
|
||||
'ConduitAPI_feed_publish_Method' => 'applications/conduit/method/feed/publish',
|
||||
'ConduitAPI_file_download_Method' => 'applications/conduit/method/file/download',
|
||||
'ConduitAPI_file_upload_Method' => 'applications/conduit/method/file/upload',
|
||||
'ConduitAPI_maniphest_info_Method' => 'applications/conduit/method/maniphest/info',
|
||||
|
@ -261,6 +262,7 @@ phutil_register_library_map(array(
|
|||
'LiskIsolationTestCase' => 'storage/lisk/dao/__tests__',
|
||||
'LiskIsolationTestDAO' => 'storage/lisk/dao/__tests__',
|
||||
'LiskIsolationTestDAOException' => 'storage/lisk/dao/__tests__',
|
||||
'ManiphestConstants' => 'applications/maniphest/constants/base',
|
||||
'ManiphestController' => 'applications/maniphest/controller/base',
|
||||
'ManiphestDAO' => 'applications/maniphest/storage/base',
|
||||
'ManiphestReplyHandler' => 'applications/maniphest/replyhandler',
|
||||
|
@ -272,7 +274,10 @@ phutil_register_library_map(array(
|
|||
'ManiphestTaskListView' => 'applications/maniphest/view/tasklist',
|
||||
'ManiphestTaskOwner' => 'applications/maniphest/constants/owner',
|
||||
'ManiphestTaskPriority' => 'applications/maniphest/constants/priority',
|
||||
'ManiphestTaskProject' => 'applications/maniphest/storage/taskproject',
|
||||
'ManiphestTaskQuery' => 'applications/maniphest/query',
|
||||
'ManiphestTaskStatus' => 'applications/maniphest/constants/status',
|
||||
'ManiphestTaskSubscriber' => 'applications/maniphest/storage/subscriber',
|
||||
'ManiphestTaskSummaryView' => 'applications/maniphest/view/tasksummary',
|
||||
'ManiphestTransaction' => 'applications/maniphest/storage/transaction',
|
||||
'ManiphestTransactionDetailView' => 'applications/maniphest/view/transactiondetail',
|
||||
|
@ -281,6 +286,7 @@ phutil_register_library_map(array(
|
|||
'ManiphestTransactionPreviewController' => 'applications/maniphest/controller/transactionpreview',
|
||||
'ManiphestTransactionSaveController' => 'applications/maniphest/controller/transactionsave',
|
||||
'ManiphestTransactionType' => 'applications/maniphest/constants/transactiontype',
|
||||
'ManiphestView' => 'applications/maniphest/view/base',
|
||||
'Phabricator404Controller' => 'applications/base/controller/404',
|
||||
'PhabricatorAuthController' => 'applications/auth/controller/base',
|
||||
'PhabricatorConduitAPIController' => 'applications/conduit/controller/api',
|
||||
|
@ -332,6 +338,17 @@ phutil_register_library_map(array(
|
|||
'PhabricatorEmailLoginController' => 'applications/auth/controller/email',
|
||||
'PhabricatorEmailTokenController' => 'applications/auth/controller/emailtoken',
|
||||
'PhabricatorEnv' => 'infrastructure/env',
|
||||
'PhabricatorFeedController' => 'applications/feed/controller/base',
|
||||
'PhabricatorFeedDAO' => 'applications/feed/storage/base',
|
||||
'PhabricatorFeedQuery' => 'applications/feed/query',
|
||||
'PhabricatorFeedStory' => 'applications/feed/story/base',
|
||||
'PhabricatorFeedStoryData' => 'applications/feed/storage/story',
|
||||
'PhabricatorFeedStoryPublisher' => 'applications/feed/publisher',
|
||||
'PhabricatorFeedStoryReference' => 'applications/feed/storage/storyreference',
|
||||
'PhabricatorFeedStoryUnknown' => 'applications/feed/story/unknown',
|
||||
'PhabricatorFeedStoryView' => 'applications/feed/view/story',
|
||||
'PhabricatorFeedStreamController' => 'applications/feed/controller/stream',
|
||||
'PhabricatorFeedView' => 'applications/feed/view/base',
|
||||
'PhabricatorFile' => 'applications/files/storage/file',
|
||||
'PhabricatorFileController' => 'applications/files/controller/base',
|
||||
'PhabricatorFileDAO' => 'applications/files/storage/base',
|
||||
|
@ -348,6 +365,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFileURI' => 'applications/files/uri',
|
||||
'PhabricatorFileUploadController' => 'applications/files/controller/upload',
|
||||
'PhabricatorFileViewController' => 'applications/files/controller/view',
|
||||
'PhabricatorGarbageCollectorDaemon' => 'infrastructure/daemon/garbagecollector',
|
||||
'PhabricatorGoodForNothingWorker' => 'infrastructure/daemon/workers/worker/goodfornothing',
|
||||
'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/selector',
|
||||
'PhabricatorHelpController' => 'applications/help/controller/base',
|
||||
|
@ -439,7 +457,6 @@ phutil_register_library_map(array(
|
|||
'PhabricatorProjectProfileController' => 'applications/project/controller/profile',
|
||||
'PhabricatorProjectProfileEditController' => 'applications/project/controller/profileedit',
|
||||
'PhabricatorProjectStatus' => 'applications/project/constants/status',
|
||||
'PhabricatorProjectTransactionSearch' => 'applications/project/transactions/search',
|
||||
'PhabricatorRedirectController' => 'applications/base/controller/redirect',
|
||||
'PhabricatorRemarkupRuleDifferential' => 'infrastructure/markup/remarkup/markuprule/differential',
|
||||
'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/remarkup/markuprule/diffusion',
|
||||
|
@ -506,6 +523,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSetup' => 'infrastructure/setup',
|
||||
'PhabricatorStandardPageView' => 'view/page/standard',
|
||||
'PhabricatorStatusController' => 'applications/status/base',
|
||||
'PhabricatorSyntaxHighlighter' => 'applications/markup/syntax',
|
||||
'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/taskmaster',
|
||||
'PhabricatorTestCase' => 'infrastructure/testing/testcase',
|
||||
'PhabricatorTimelineCursor' => 'infrastructure/daemon/timeline/storage/cursor',
|
||||
|
@ -656,6 +674,7 @@ phutil_register_library_map(array(
|
|||
'ConduitAPI_differential_updateunitresults_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_diffusion_getcommits_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_feed_publish_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_file_download_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod',
|
||||
'ConduitAPI_maniphest_info_Method' => 'ConduitAPIMethod',
|
||||
|
@ -764,13 +783,20 @@ phutil_register_library_map(array(
|
|||
'ManiphestTaskDetailController' => 'ManiphestController',
|
||||
'ManiphestTaskEditController' => 'ManiphestController',
|
||||
'ManiphestTaskListController' => 'ManiphestController',
|
||||
'ManiphestTaskListView' => 'AphrontView',
|
||||
'ManiphestTaskSummaryView' => 'AphrontView',
|
||||
'ManiphestTaskListView' => 'ManiphestView',
|
||||
'ManiphestTaskOwner' => 'ManiphestConstants',
|
||||
'ManiphestTaskPriority' => 'ManiphestConstants',
|
||||
'ManiphestTaskProject' => 'ManiphestDAO',
|
||||
'ManiphestTaskStatus' => 'ManiphestConstants',
|
||||
'ManiphestTaskSubscriber' => 'ManiphestDAO',
|
||||
'ManiphestTaskSummaryView' => 'ManiphestView',
|
||||
'ManiphestTransaction' => 'ManiphestDAO',
|
||||
'ManiphestTransactionDetailView' => 'AphrontView',
|
||||
'ManiphestTransactionListView' => 'AphrontView',
|
||||
'ManiphestTransactionDetailView' => 'ManiphestView',
|
||||
'ManiphestTransactionListView' => 'ManiphestView',
|
||||
'ManiphestTransactionPreviewController' => 'ManiphestController',
|
||||
'ManiphestTransactionSaveController' => 'ManiphestController',
|
||||
'ManiphestTransactionType' => 'ManiphestConstants',
|
||||
'ManiphestView' => 'AphrontView',
|
||||
'Phabricator404Controller' => 'PhabricatorController',
|
||||
'PhabricatorAuthController' => 'PhabricatorController',
|
||||
'PhabricatorConduitAPIController' => 'PhabricatorConduitController',
|
||||
|
@ -819,6 +845,14 @@ phutil_register_library_map(array(
|
|||
'PhabricatorEditPreferencesController' => 'PhabricatorPreferencesController',
|
||||
'PhabricatorEmailLoginController' => 'PhabricatorAuthController',
|
||||
'PhabricatorEmailTokenController' => 'PhabricatorAuthController',
|
||||
'PhabricatorFeedController' => 'PhabricatorController',
|
||||
'PhabricatorFeedDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorFeedStoryData' => 'PhabricatorFeedDAO',
|
||||
'PhabricatorFeedStoryReference' => 'PhabricatorFeedDAO',
|
||||
'PhabricatorFeedStoryUnknown' => 'PhabricatorFeedStory',
|
||||
'PhabricatorFeedStoryView' => 'PhabricatorFeedView',
|
||||
'PhabricatorFeedStreamController' => 'PhabricatorFeedController',
|
||||
'PhabricatorFeedView' => 'AphrontView',
|
||||
'PhabricatorFile' => 'PhabricatorFileDAO',
|
||||
'PhabricatorFileController' => 'PhabricatorController',
|
||||
'PhabricatorFileDAO' => 'PhabricatorLiskDAO',
|
||||
|
@ -834,6 +868,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorFileTransformController' => 'PhabricatorFileController',
|
||||
'PhabricatorFileUploadController' => 'PhabricatorFileController',
|
||||
'PhabricatorFileViewController' => 'PhabricatorFileController',
|
||||
'PhabricatorGarbageCollectorDaemon' => 'PhabricatorDaemon',
|
||||
'PhabricatorGoodForNothingWorker' => 'PhabricatorWorker',
|
||||
'PhabricatorHelpController' => 'PhabricatorController',
|
||||
'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController',
|
||||
|
|
|
@ -330,6 +330,10 @@ class AphrontDefaultApplicationConfiguration
|
|||
'delete/(?P<id>\d+)/$'
|
||||
=> 'PhabricatorCountdownDeleteController'
|
||||
),
|
||||
|
||||
'/feed/' => array(
|
||||
'$' => 'PhabricatorFeedStreamController',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,10 +31,17 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
|||
}
|
||||
|
||||
$next_uri = $this->getRequest()->getPath();
|
||||
if ($next_uri == '/login/') {
|
||||
$next_uri = null;
|
||||
$request->setCookie('next_uri', $next_uri);
|
||||
if ($next_uri == '/login/' && !$request->isFormPost()) {
|
||||
// The user went straight to /login/, so presumably they want to go
|
||||
// to the dashboard upon logging in. Because, you know, that's logical.
|
||||
// And people are logical. Sometimes... Fine, no they're not.
|
||||
// We check for POST here because getPath() would get reset to /login/.
|
||||
$request->setCookie('next_uri', '/');
|
||||
}
|
||||
|
||||
// Always use $request->getCookie('next_uri', '/') after the above.
|
||||
|
||||
$password_auth = PhabricatorEnv::getEnvConfig('auth.password-auth-enabled');
|
||||
|
||||
$forms = array();
|
||||
|
@ -66,7 +73,7 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
|||
$request->setCookie('phsid', $session_key);
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI('/');
|
||||
->setURI($request->getCookie('next_uri', '/'));
|
||||
} else {
|
||||
$log = PhabricatorUserLog::newLog(
|
||||
null,
|
||||
|
@ -93,7 +100,6 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
|||
$form
|
||||
->setUser($request->getUser())
|
||||
->setAction('/login/')
|
||||
->addHiddenInput('next', $next_uri)
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel('Username/Email')
|
||||
|
@ -115,8 +121,6 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
|||
$forms['Phabricator Login'] = $form;
|
||||
}
|
||||
|
||||
$oauth_state = $next_uri;
|
||||
|
||||
$providers = array(
|
||||
PhabricatorOAuthProvider::PROVIDER_FACEBOOK,
|
||||
PhabricatorOAuthProvider::PROVIDER_GITHUB,
|
||||
|
@ -160,7 +164,6 @@ class PhabricatorLoginController extends PhabricatorAuthController {
|
|||
->addHiddenInput('client_id', $client_id)
|
||||
->addHiddenInput('redirect_uri', $redirect_uri)
|
||||
->addHiddenInput('scope', $minimum_scope)
|
||||
->addHiddenInput('state', $oauth_state)
|
||||
->setUser($request->getUser())
|
||||
->setMethod('GET')
|
||||
->appendChild(
|
||||
|
|
|
@ -135,12 +135,7 @@ class PhabricatorOAuthLoginController extends PhabricatorAuthController {
|
|||
->setURI('/settings/page/'.$provider_key.'/');
|
||||
}
|
||||
|
||||
$next_uri = '/';
|
||||
if ($this->oauthState) {
|
||||
// Make sure a blind redirect to evil.com is impossible.
|
||||
$uri = new PhutilURI($this->oauthState);
|
||||
$next_uri = $uri->getPath();
|
||||
}
|
||||
$next_uri = $request->getCookie('next_uri', '/');
|
||||
|
||||
// Login with known auth.
|
||||
|
||||
|
@ -158,6 +153,7 @@ class PhabricatorOAuthLoginController extends PhabricatorAuthController {
|
|||
|
||||
$request->setCookie('phusr', $known_user->getUsername());
|
||||
$request->setCookie('phsid', $session_key);
|
||||
$request->clearCookie('next_uri');
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($next_uri);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class PhabricatorConduitAPIController
|
||||
extends PhabricatorConduitController {
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
abstract class PhabricatorConduitController extends PhabricatorController {
|
||||
|
||||
public function buildStandardPageResponse($view, array $data) {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class PhabricatorConduitConsoleController
|
||||
extends PhabricatorConduitController {
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class PhabricatorConduitLogController extends PhabricatorConduitController {
|
||||
|
||||
public function processRequest() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class PhabricatorConduitTokenController extends PhabricatorConduitController {
|
||||
|
||||
public function processRequest() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
abstract class ConduitAPIMethod {
|
||||
|
||||
abstract public function getMethodDescription();
|
||||
|
@ -63,4 +66,29 @@ abstract class ConduitAPIMethod {
|
|||
return str_replace('_', '.', $method_fragment);
|
||||
}
|
||||
|
||||
protected function validateHost($host) {
|
||||
if (!$host) {
|
||||
// If the client doesn't send a host key, don't complain. We should in
|
||||
// the future, but this change isn't severe enough to bump the protocol
|
||||
// version.
|
||||
|
||||
// TODO: Remove this once the protocol version gets bumped past 2 (i.e.,
|
||||
// require the host key be present and valid).
|
||||
return;
|
||||
}
|
||||
|
||||
$host = new PhutilURI($host);
|
||||
$host->setPath('/');
|
||||
$host = (string)$host;
|
||||
|
||||
$self = PhabricatorEnv::getProductionURI('/');
|
||||
if ($self !== $host) {
|
||||
throw new Exception(
|
||||
"Your client is connecting to this install as '{$host}', but it is ".
|
||||
"configured as '{$self}'. The client and server must use the exact ".
|
||||
"same URI to identify the install. Edit your .arcconfig or ".
|
||||
"phabricator/conf so they agree on the URI for the install.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
|
||||
phutil_require_module('phutil', 'parser/uri');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_conduit_connect_Method extends ConduitAPIMethod {
|
||||
|
||||
public function shouldRequireAuthentication() {
|
||||
|
@ -34,6 +37,7 @@ class ConduitAPI_conduit_connect_Method extends ConduitAPIMethod {
|
|||
'user' => 'optional string',
|
||||
'authToken' => 'optional int',
|
||||
'authSignature' => 'optional string',
|
||||
'host' => 'required string',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -67,6 +71,8 @@ class ConduitAPI_conduit_connect_Method extends ConduitAPIMethod {
|
|||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
|
||||
$this->validateHost($request->getValue('host'));
|
||||
|
||||
$client = $request->getValue('client');
|
||||
$client_version = (int)$request->getValue('clientVersion');
|
||||
$client_description = (string)$request->getValue('clientDescription');
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_conduit_getcertificate_Method extends ConduitAPIMethod {
|
||||
|
||||
public function shouldRequireAuthentication() {
|
||||
|
@ -29,6 +32,7 @@ class ConduitAPI_conduit_getcertificate_Method extends ConduitAPIMethod {
|
|||
public function defineParamTypes() {
|
||||
return array(
|
||||
'token' => 'required string',
|
||||
'host' => 'required string',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -46,6 +50,7 @@ class ConduitAPI_conduit_getcertificate_Method extends ConduitAPIMethod {
|
|||
}
|
||||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
$this->validateHost($request->getValue('host'));
|
||||
|
||||
$failed_attempts = PhabricatorUserLog::loadRecentEventsFromThisIP(
|
||||
PhabricatorUserLog::ACTION_CONDUIT_CERTIFICATE_FAILURE,
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_conduit_ping_Method extends ConduitAPIMethod {
|
||||
|
||||
public function shouldRequireAuthentication() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_daemon_launched_Method extends ConduitAPIMethod {
|
||||
|
||||
public function shouldRequireAuthentication() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_daemon_log_Method extends ConduitAPIMethod {
|
||||
|
||||
public function shouldRequireAuthentication() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_creatediff_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_createrevision_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
@ -26,7 +29,6 @@ class ConduitAPI_differential_createrevision_Method extends ConduitAPIMethod {
|
|||
return array(
|
||||
'diffid' => 'required diffid',
|
||||
'fields' => 'required dict',
|
||||
'user' => 'required guid',
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -51,7 +53,7 @@ class ConduitAPI_differential_createrevision_Method extends ConduitAPIMethod {
|
|||
$revision = DifferentialRevisionEditor::newRevisionFromConduitWithDiff(
|
||||
$fields,
|
||||
$diff,
|
||||
$request->getValue('user')); // TODO: Should be authoritative
|
||||
$request->getUser()->getPHID());
|
||||
|
||||
return array(
|
||||
'revisionid' => $revision->getID(),
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_find_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_getalldiffs_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_getcommitmessage_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_getcommitpaths_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_getdiff_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_getrevision_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_getrevisionfeedback_Method
|
||||
extends ConduitAPIMethod {
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_markcommitted_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_parsecommitmessage_Method
|
||||
extends ConduitAPIMethod {
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_setdiffproperty_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_updaterevision_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,8 +16,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_updatetaskrevisionassoc_Method
|
||||
extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return "Given a task together with its original and new associated ".
|
||||
"revisions, update the revisions for their attached_tasks.";
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_differential_updateunitresults_Method
|
||||
extends ConduitAPIMethod {
|
||||
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_diffusion_getcommits_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_diffusion_getrecentcommitsbypath_Method
|
||||
extends ConduitAPIMethod {
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_feed_publish_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
return "(UNSTABLE!!!) Publish a story to the feed.";
|
||||
}
|
||||
|
||||
public function defineParamTypes() {
|
||||
return array(
|
||||
'type' => 'required string',
|
||||
'data' => 'required dict',
|
||||
'time' => 'optional int',
|
||||
);
|
||||
}
|
||||
|
||||
public function defineErrorTypes() {
|
||||
return array(
|
||||
);
|
||||
}
|
||||
|
||||
public function defineReturnType() {
|
||||
return 'nonempty phid';
|
||||
}
|
||||
|
||||
protected function execute(ConduitAPIRequest $request) {
|
||||
$type = $request->getValue('type');
|
||||
$data = $request->getValue('data');
|
||||
$time = $request->getValue('time');
|
||||
|
||||
$author_phid = $request->getUser()->getPHID();
|
||||
$phids = array($author_phid);
|
||||
|
||||
$publisher = new PhabricatorFeedStoryPublisher();
|
||||
$publisher->setStoryType($type);
|
||||
$publisher->setStoryData($data);
|
||||
$publisher->setStoryTime($time);
|
||||
$publisher->setRelatedPHIDs($phids);
|
||||
$publisher->setStoryAuthorPHID($author_phid);
|
||||
|
||||
$data = $publisher->publish();
|
||||
|
||||
return $data->getPHID();
|
||||
}
|
||||
|
||||
}
|
13
src/applications/conduit/method/feed/publish/__init__.php
Normal file
13
src/applications/conduit/method/feed/publish/__init__.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/conduit/method/base');
|
||||
phutil_require_module('phabricator', 'applications/feed/publisher');
|
||||
|
||||
|
||||
phutil_require_source('ConduitAPI_feed_publish_Method.php');
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_file_download_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_file_upload_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_maniphest_info_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_paste_info_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_path_getowners_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_user_find_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPI_user_whoami_Method extends ConduitAPIMethod {
|
||||
|
||||
public function getMethodDescription() {
|
||||
|
|
|
@ -16,5 +16,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitException extends Exception {
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class ConduitAPIRequest {
|
||||
|
||||
protected $params;
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
abstract class PhabricatorConduitDAO extends PhabricatorLiskDAO {
|
||||
|
||||
public function getApplicationName() {
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class PhabricatorConduitConnectionLog extends PhabricatorConduitDAO {
|
||||
|
||||
protected $client;
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class PhabricatorConduitMethodCallLog extends PhabricatorConduitDAO {
|
||||
|
||||
protected $connectionID;
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group conduit
|
||||
*/
|
||||
class PhabricatorConduitCertificateToken extends PhabricatorConduitDAO {
|
||||
|
||||
protected $userPHID;
|
||||
|
|
|
@ -43,11 +43,46 @@ final class PhabricatorDaemonLogEventsView extends AphrontView {
|
|||
}
|
||||
|
||||
foreach ($this->events as $event) {
|
||||
|
||||
// Limit display log size. If a daemon gets stuck in an output loop this
|
||||
// page can be like >100MB if we don't truncate stuff. Try to do cheap
|
||||
// line-based truncation first, and fall back to expensive UTF-8 character
|
||||
// truncation if that doesn't get things short enough.
|
||||
|
||||
$message = $event->getMessage();
|
||||
|
||||
$more_lines = null;
|
||||
$more_chars = null;
|
||||
$line_limit = 12;
|
||||
if (substr_count($message, "\n") > $line_limit) {
|
||||
$message = explode("\n", $message);
|
||||
$more_lines = count($message) - $line_limit;
|
||||
$message = array_slice($message, 0, $line_limit);
|
||||
$message = implode("\n", $message);
|
||||
}
|
||||
|
||||
$char_limit = 8192;
|
||||
if (strlen($message) > $char_limit) {
|
||||
$message = phutil_utf8v($message);
|
||||
$more_chars = count($message) - $char_limit;
|
||||
$message = array_slice($message, 0, $char_limit);
|
||||
$message = implode('', $message);
|
||||
}
|
||||
|
||||
$more = null;
|
||||
if ($more_chars) {
|
||||
$more = number_format($more_chars);
|
||||
$more = "\n<... {$more} more characters ...>";
|
||||
} else if ($more_lines) {
|
||||
$more = number_format($more_lines);
|
||||
$more = "\n<... {$more} more lines ...>";
|
||||
}
|
||||
|
||||
$row = array(
|
||||
phutil_escape_html($event->getLogType()),
|
||||
phabricator_date($event->getEpoch(), $this->user),
|
||||
phabricator_time($event->getEpoch(), $this->user),
|
||||
str_replace("\n", '<br />', phutil_escape_html($event->getMessage())),
|
||||
str_replace("\n", '<br />', phutil_escape_html($message.$more)),
|
||||
);
|
||||
|
||||
if ($this->combinedLog) {
|
||||
|
|
|
@ -11,6 +11,7 @@ phutil_require_module('phabricator', 'view/control/table');
|
|||
phutil_require_module('phabricator', 'view/utils');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorDaemonLogEventsView.php');
|
||||
|
|
|
@ -57,6 +57,7 @@ class DifferentialRevisionEditController extends DifferentialController {
|
|||
|
||||
$e_title = true;
|
||||
$e_testplan = true;
|
||||
$e_reviewers = null;
|
||||
$errors = array();
|
||||
|
||||
$revision->loadRelationships();
|
||||
|
@ -71,17 +72,22 @@ class DifferentialRevisionEditController extends DifferentialController {
|
|||
if (!strlen(trim($revision->getTitle()))) {
|
||||
$errors[] = 'You must provide a title.';
|
||||
$e_title = 'Required';
|
||||
} else {
|
||||
$e_title = null;
|
||||
}
|
||||
|
||||
if (!strlen(trim($revision->getTestPlan()))) {
|
||||
$errors[] = 'You must provide a test plan.';
|
||||
$e_testplan = 'Required';
|
||||
} else {
|
||||
$e_testplan = null;
|
||||
}
|
||||
|
||||
$user_phid = $request->getUser()->getPHID();
|
||||
|
||||
if (in_array($user_phid, $request->getArr('reviewers'))) {
|
||||
$errors[] = 'You may not review your own revision.';
|
||||
$e_reviewers = 'Invalid';
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
|
@ -172,6 +178,7 @@ class DifferentialRevisionEditController extends DifferentialController {
|
|||
->setLabel('Reviewers')
|
||||
->setName('reviewers')
|
||||
->setDatasource('/typeahead/common/users/')
|
||||
->setError($e_reviewers)
|
||||
->setValue($reviewer_map))
|
||||
->appendChild(
|
||||
id(new AphrontFormTokenizerControl())
|
||||
|
|
|
@ -319,4 +319,12 @@ EOTEXT;
|
|||
return $this->heraldTranscriptURI;
|
||||
}
|
||||
|
||||
protected function renderHandleList(array $handles, array $phids) {
|
||||
$names = array();
|
||||
foreach ($phids as $phid) {
|
||||
$names[] = $handles[$phid]->getName();
|
||||
}
|
||||
return implode(', ', $names);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ class DifferentialCCWelcomeMail extends DifferentialReviewRequestMail {
|
|||
$body = array();
|
||||
|
||||
$body[] = "{$actor} added you to the CC list for the revision \"{$name}\".";
|
||||
$body[] = $this->renderReviewersLine();
|
||||
$body[] = null;
|
||||
|
||||
$body[] = $this->renderReviewRequestBody();
|
||||
|
|
|
@ -71,6 +71,32 @@ class DifferentialCommentMail extends DifferentialMail {
|
|||
$body = array();
|
||||
|
||||
$body[] = "{$actor} has {$verb} the revision \"{$name}\".";
|
||||
|
||||
// If the commented added reviewers or CCs, list them explicitly.
|
||||
$meta = $comment->getMetadata();
|
||||
$m_reviewers = idx(
|
||||
$meta,
|
||||
DifferentialComment::METADATA_ADDED_REVIEWERS,
|
||||
array());
|
||||
$m_cc = idx(
|
||||
$meta,
|
||||
DifferentialComment::METADATA_ADDED_CCS,
|
||||
array());
|
||||
$load = array_merge($m_reviewers, $m_cc);
|
||||
if ($load) {
|
||||
$handles = id(new PhabricatorObjectHandleData($load))->loadHandles();
|
||||
if ($m_reviewers) {
|
||||
$body[] = 'Added Reviewers: '.$this->renderHandleList(
|
||||
$handles,
|
||||
$m_reviewers);
|
||||
}
|
||||
if ($m_cc) {
|
||||
$body[] = 'Added CCs: '.$this->renderHandleList(
|
||||
$handles,
|
||||
$m_cc);
|
||||
}
|
||||
}
|
||||
|
||||
$body[] = null;
|
||||
|
||||
$content = $comment->getContent();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
phutil_require_module('phabricator', 'applications/differential/constants/action');
|
||||
phutil_require_module('phabricator', 'applications/differential/constants/revisionstatus');
|
||||
phutil_require_module('phabricator', 'applications/differential/mail/base');
|
||||
phutil_require_module('phabricator', 'applications/differential/storage/comment');
|
||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ class DifferentialNewDiffMail extends DifferentialReviewRequestMail {
|
|||
} else {
|
||||
$body[] = "{$actor} updated the revision \"{$name}\".";
|
||||
}
|
||||
$body[] = $this->renderReviewersLine();
|
||||
$body[] = null;
|
||||
|
||||
$body[] = $this->renderReviewRequestBody();
|
||||
|
|
|
@ -39,6 +39,12 @@ abstract class DifferentialReviewRequestMail extends DifferentialMail {
|
|||
$this->setChangesets($changesets);
|
||||
}
|
||||
|
||||
protected function renderReviewersLine() {
|
||||
$reviewers = $this->getRevision()->getReviewers();
|
||||
$handles = id(new PhabricatorObjectHandleData($reviewers))->loadHandles();
|
||||
return 'Reviewers: '.$this->renderHandleList($handles, $reviewers);
|
||||
}
|
||||
|
||||
protected function renderReviewRequestBody() {
|
||||
$revision = $this->getRevision();
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/differential/mail/base');
|
||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('DifferentialReviewRequestMail.php');
|
||||
|
|
|
@ -27,7 +27,6 @@ class DifferentialChangesetParser {
|
|||
protected $parsedHunk = false;
|
||||
|
||||
protected $filename = null;
|
||||
protected $filetype = null;
|
||||
protected $missingOld = array();
|
||||
protected $missingNew = array();
|
||||
|
||||
|
@ -161,10 +160,7 @@ class DifferentialChangesetParser {
|
|||
|
||||
public function setFilename($filename) {
|
||||
$this->filename = $filename;
|
||||
if (strpos($filename, '.', 1) !== false) {
|
||||
$parts = explode('.', $filename);
|
||||
$this->filetype = end($parts);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHandles(array $handles) {
|
||||
|
@ -341,6 +337,21 @@ class DifferentialChangesetParser {
|
|||
switch ($this->whitespaceMode) {
|
||||
case self::WHITESPACE_IGNORE_TRAILING:
|
||||
if (rtrim($o_desc['text']) == rtrim($n_desc['text'])) {
|
||||
if ($o_desc['type']) {
|
||||
// If we're converting this into an unchanged line because of
|
||||
// a trailing whitespace difference, mark it as a whitespace
|
||||
// change so we can show "This file was modified only by
|
||||
// adding or removing trailing whitespace." instead of
|
||||
// "This file was not modified.".
|
||||
$whitelines = true;
|
||||
}
|
||||
$similar = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// In this case, the lines are similar if there is no change type
|
||||
// (that is, just trust the diff algorithm).
|
||||
if (!$o_desc['type']) {
|
||||
$similar = true;
|
||||
}
|
||||
break;
|
||||
|
@ -349,7 +360,6 @@ class DifferentialChangesetParser {
|
|||
$o_desc['type'] = null;
|
||||
$n_desc['type'] = null;
|
||||
$skip_intra[count($old)] = true;
|
||||
$whitelines = true;
|
||||
} else {
|
||||
$changed = true;
|
||||
}
|
||||
|
@ -700,7 +710,7 @@ class DifferentialChangesetParser {
|
|||
foreach ($vector as $ii => $char) {
|
||||
$result[] = $char;
|
||||
if (isset($break_here[$ii])) {
|
||||
$result[] = "<span class=\"over-the-line\">!</span><br />";
|
||||
$result[] = "<span class=\"over-the-line\">\xE2\xAC\x85</span><br />";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -709,7 +719,7 @@ class DifferentialChangesetParser {
|
|||
|
||||
protected function getHighlightFuture($corpus) {
|
||||
return $this->highlightEngine->getHighlightFuture(
|
||||
$this->filetype,
|
||||
$this->highlightEngine->getLanguageFromFilename($this->filename),
|
||||
$corpus);
|
||||
}
|
||||
|
||||
|
@ -744,24 +754,38 @@ class DifferentialChangesetParser {
|
|||
$changeset->getFileType() == DifferentialChangeType::FILE_SYMLINK) {
|
||||
if ($skip_cache || !$this->loadCache()) {
|
||||
|
||||
$ignore_all = ($this->whitespaceMode == self::WHITESPACE_IGNORE_ALL);
|
||||
|
||||
// The "ignore all whitespace" algorithm depends on rediffing the
|
||||
// files, and we currently need complete representations of both
|
||||
// files to do anything reasonable. If we only have parts of the files,
|
||||
// don't use the "ignore all" algorithm.
|
||||
$can_use_ignore_all = true;
|
||||
$hunks = $changeset->getHunks();
|
||||
if (count($hunks) !== 1) {
|
||||
$can_use_ignore_all = false;
|
||||
} else {
|
||||
$first_hunk = reset($hunks);
|
||||
if ($first_hunk->getOldOffset() != 1 ||
|
||||
$first_hunk->getNewOffset() != 1) {
|
||||
$can_use_ignore_all = false;
|
||||
if ($ignore_all) {
|
||||
$hunks = $changeset->getHunks();
|
||||
if (count($hunks) !== 1) {
|
||||
$ignore_all = false;
|
||||
} else {
|
||||
$first_hunk = reset($hunks);
|
||||
if ($first_hunk->getOldOffset() != 1 ||
|
||||
$first_hunk->getNewOffset() != 1) {
|
||||
$ignore_all = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->whitespaceMode == self::WHITESPACE_IGNORE_ALL &&
|
||||
$can_use_ignore_all) {
|
||||
if ($ignore_all) {
|
||||
$old_file = $changeset->makeOldFile();
|
||||
$new_file = $changeset->makeNewFile();
|
||||
if ($old_file == $new_file) {
|
||||
// If the old and new files are exactly identical, the synthetic
|
||||
// diff below will give us nonsense and whitespace modes are
|
||||
// irrelevant anyway. This occurs when you, e.g., copy a file onto
|
||||
// itself in Subversion (see T271).
|
||||
$ignore_all = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($ignore_all) {
|
||||
|
||||
// Huge mess. Generate a "-bw" (ignore all whitespace changes) diff,
|
||||
// parse it out, and then play a shell game with the parsed format
|
||||
|
@ -773,8 +797,8 @@ class DifferentialChangesetParser {
|
|||
|
||||
$old_tmp = new TempFile();
|
||||
$new_tmp = new TempFile();
|
||||
Filesystem::writeFile($old_tmp, $changeset->makeOldFile());
|
||||
Filesystem::writeFile($new_tmp, $changeset->makeNewFile());
|
||||
Filesystem::writeFile($old_tmp, $old_file);
|
||||
Filesystem::writeFile($new_tmp, $new_file);
|
||||
list($err, $diff) = exec_manual(
|
||||
'diff -bw -U65535 %s %s ',
|
||||
$old_tmp,
|
||||
|
@ -849,10 +873,7 @@ EOSYNTHETIC;
|
|||
$this->isTopLevel = (($range_start === null) && ($range_len === null));
|
||||
|
||||
|
||||
$this->highlightEngine = new PhutilDefaultSyntaxHighlighterEngine();
|
||||
$this->highlightEngine->setConfig(
|
||||
'pygments.enabled',
|
||||
PhabricatorEnv::getEnvConfig('pygments.enabled'));
|
||||
$this->highlightEngine = PhabricatorSyntaxHighlighter::newEngine();
|
||||
|
||||
$this->tryCacheStuff();
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ phutil_require_module('phabricator', 'applications/differential/storage/changese
|
|||
phutil_require_module('phabricator', 'applications/differential/storage/diff');
|
||||
phutil_require_module('phabricator', 'applications/differential/view/inlinecomment');
|
||||
phutil_require_module('phabricator', 'applications/files/uri');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
phutil_require_module('phabricator', 'applications/markup/syntax');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
|
||||
|
@ -24,7 +24,6 @@ phutil_require_module('phutil', 'filesystem/tempfile');
|
|||
phutil_require_module('phutil', 'future');
|
||||
phutil_require_module('phutil', 'future/exec');
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'markup/syntax/engine/default');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
|
|
|
@ -31,6 +31,10 @@ class DifferentialReplyHandler extends PhabricatorMailReplyHandler {
|
|||
return $this->getDefaultPrivateReplyHandlerEmailAddress($handle, 'D');
|
||||
}
|
||||
|
||||
public function getPublicReplyHandlerEmailAddress() {
|
||||
return $this->getDefaultPublicReplyHandlerEmailAddress('D');
|
||||
}
|
||||
|
||||
public function getReplyHandlerDomain() {
|
||||
return PhabricatorEnv::getEnvConfig(
|
||||
'metamta.differential.reply-handler-domain');
|
||||
|
|
|
@ -179,13 +179,11 @@ class DiffusionBrowseFileController extends DiffusionController {
|
|||
|
||||
list($text_list, $rev_list, $blame_dict) = $file_query->getBlameData();
|
||||
|
||||
$highlightEngine = new PhutilDefaultSyntaxHighlighterEngine();
|
||||
$highlightEngine->setConfig(
|
||||
'pygments.enabled',
|
||||
PhabricatorEnv::getEnvConfig('pygments.enabled'));
|
||||
|
||||
$text_list = explode("\n", $highlightEngine->highlightSource($path,
|
||||
implode("\n", $text_list)));
|
||||
$text_list = implode("\n", $text_list);
|
||||
$text_list = PhabricatorSyntaxHighlighter::highlightWithFilename(
|
||||
$path,
|
||||
$text_list);
|
||||
$text_list = explode("\n", $text_list);
|
||||
|
||||
$rows = $this->buildDisplayRows($text_list, $rev_list, $blame_dict,
|
||||
$needs_blame, $drequest, $file_query, $selected);
|
||||
|
|
|
@ -8,13 +8,12 @@
|
|||
|
||||
phutil_require_module('phabricator', 'applications/diffusion/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/diffusion/query/filecontent/base');
|
||||
phutil_require_module('phabricator', 'applications/markup/syntax');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/api');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'markup/syntax/engine/default');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
abstract class PhabricatorFeedController extends PhabricatorController {
|
||||
|
||||
public function buildStandardPageResponse($view, array $data) {
|
||||
$page = $this->buildStandardPageView();
|
||||
|
||||
$page->setApplicationName('Feed');
|
||||
$page->setBaseURI('/feed/');
|
||||
$page->setTitle(idx($data, 'title'));
|
||||
$page->setGlyph("\xE2\x88\x9E");
|
||||
$page->appendChild($view);
|
||||
|
||||
$response = new AphrontWebpageResponse();
|
||||
return $response->setContent($page->render());
|
||||
}
|
||||
|
||||
}
|
15
src/applications/feed/controller/base/__init__.php
Normal file
15
src/applications/feed/controller/base/__init__.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/webpage');
|
||||
phutil_require_module('phabricator', 'applications/base/controller/base');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedController.php');
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorFeedStreamController extends PhabricatorFeedController {
|
||||
|
||||
public function processRequest() {
|
||||
|
||||
$query = new PhabricatorFeedQuery();
|
||||
$stories = $query->execute();
|
||||
|
||||
$views = array();
|
||||
foreach ($stories as $story) {
|
||||
$views[] = $story->renderView();
|
||||
}
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$views,
|
||||
array(
|
||||
'title' => 'Feed',
|
||||
));
|
||||
}
|
||||
}
|
13
src/applications/feed/controller/stream/__init__.php
Normal file
13
src/applications/feed/controller/stream/__init__.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/feed/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/feed/query');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedStreamController.php');
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorFeedStoryPublisher {
|
||||
|
||||
private $relatedPHIDs;
|
||||
private $storyType;
|
||||
private $storyData;
|
||||
private $storyTime;
|
||||
private $storyAuthorPHID;
|
||||
|
||||
public function setRelatedPHIDs(array $phids) {
|
||||
$this->relatedPHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStoryType($story_type) {
|
||||
$this->storyType = $story_type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStoryData(array $data) {
|
||||
$this->storyData = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStoryTime($time) {
|
||||
$this->storyTime = $time;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStoryAuthorPHID($phid) {
|
||||
$this->storyAuthorPHID = $phid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function publish() {
|
||||
if (!$this->relatedPHIDs) {
|
||||
throw new Exception("There are no PHIDs related to this story!");
|
||||
}
|
||||
|
||||
if (!$this->storyType) {
|
||||
throw new Exception("Call setStoryType() before publishing!");
|
||||
}
|
||||
|
||||
$chrono_key = $this->generateChronologicalKey();
|
||||
|
||||
$story = new PhabricatorFeedStoryData();
|
||||
$story->setStoryType($this->storyType);
|
||||
$story->setStoryData($this->storyData);
|
||||
$story->setAuthorPHID($this->storyAuthorPHID);
|
||||
$story->setChronologicalKey($chrono_key);
|
||||
$story->save();
|
||||
|
||||
$ref = new PhabricatorFeedStoryReference();
|
||||
|
||||
$sql = array();
|
||||
$conn = $ref->establishConnection('w');
|
||||
foreach ($this->relatedPHIDs as $phid) {
|
||||
$sql[] = qsprintf(
|
||||
$conn,
|
||||
'(%s, %s)',
|
||||
$phid,
|
||||
$chrono_key);
|
||||
}
|
||||
|
||||
queryfx(
|
||||
$conn,
|
||||
'INSERT INTO %T (objectPHID, chronologicalKey) VALUES %Q',
|
||||
$ref->getTableName(),
|
||||
implode(', ', $sql));
|
||||
|
||||
return $story;
|
||||
}
|
||||
|
||||
/**
|
||||
* We generate a unique chronological key for each story type because we want
|
||||
* to be able to page through the stream with a cursor (i.e., select stories
|
||||
* after ID = X) so we can efficiently perform filtering after selecting data,
|
||||
* and multiple stories with the same ID make this cumbersome without putting
|
||||
* a bunch of logic in the client. We could use the primary key, but that
|
||||
* would prevent publishing stories which happened in the past. Since it's
|
||||
* potentially useful to do that (e.g., if you're importing another data
|
||||
* source) build a unique key for each story which has chronological ordering.
|
||||
*
|
||||
* @return string A unique, time-ordered key which identifies the story.
|
||||
*/
|
||||
private function generateChronologicalKey() {
|
||||
// Use the epoch timestamp for the upper 32 bits of the key. Default to
|
||||
// the current time if the story doesn't have an explicit timestamp.
|
||||
$time = nonempty($this->storyTime, time());
|
||||
|
||||
// Generate a random number for the lower 32 bits of the key.
|
||||
$rand = head(unpack('L', Filesystem::readRandomBytes(4)));
|
||||
|
||||
return ($time << 32) + ($rand);
|
||||
}
|
||||
}
|
18
src/applications/feed/publisher/__init__.php
Normal file
18
src/applications/feed/publisher/__init__.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/feed/storage/story');
|
||||
phutil_require_module('phabricator', 'applications/feed/storage/storyreference');
|
||||
phutil_require_module('phabricator', 'storage/qsprintf');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
|
||||
phutil_require_module('phutil', 'filesystem');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedStoryPublisher.php');
|
95
src/applications/feed/query/PhabricatorFeedQuery.php
Normal file
95
src/applications/feed/query/PhabricatorFeedQuery.php
Normal file
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorFeedQuery {
|
||||
|
||||
private $filterPHIDs;
|
||||
private $limit = 100;
|
||||
private $after;
|
||||
|
||||
public function setFilterPHIDs(array $phids) {
|
||||
$this->filterPHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setLimit($limit) {
|
||||
$this->limit = $limit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAfter($after) {
|
||||
$this->after = $after;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
|
||||
$ref_table = new PhabricatorFeedStoryReference();
|
||||
$story_table = new PhabricatorFeedStoryData();
|
||||
|
||||
$conn = $story_table->establishConnection('r');
|
||||
|
||||
$where = array();
|
||||
if ($this->filterPHIDs) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'ref.objectPHID IN (%Ls)',
|
||||
$this->filterPHIDs);
|
||||
}
|
||||
|
||||
if ($where) {
|
||||
$where = 'WHERE ('.implode(') AND (', $where).')';
|
||||
} else {
|
||||
$where = '';
|
||||
}
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn,
|
||||
'SELECT story.* FROM %T ref
|
||||
JOIN %T story ON ref.chronologicalKey = story.chronologicalKey
|
||||
%Q
|
||||
GROUP BY story.chronologicalKey
|
||||
ORDER BY story.chronologicalKey DESC
|
||||
LIMIT %d',
|
||||
$ref_table->getTableName(),
|
||||
$story_table->getTableName(),
|
||||
$where,
|
||||
$this->limit);
|
||||
$data = $story_table->loadAllFromArray($data);
|
||||
|
||||
$stories = array();
|
||||
foreach ($data as $story_data) {
|
||||
$class = $story_data->getStoryType();
|
||||
|
||||
try {
|
||||
if (!class_exists($class) ||
|
||||
!is_subclass_of($class, 'PhabricatorFeedStory')) {
|
||||
$class = 'PhabricatorFeedStoryUnknown';
|
||||
}
|
||||
} catch (PhutilMissingSymbolException $ex) {
|
||||
// If the class can't be loaded, libphutil will throw an exception.
|
||||
// Render the story using the unknown story view.
|
||||
$class = 'PhabricatorFeedStoryUnknown';
|
||||
}
|
||||
|
||||
$stories[] = newv($class, array($story_data));
|
||||
}
|
||||
|
||||
return $stories;
|
||||
}
|
||||
}
|
17
src/applications/feed/query/__init__.php
Normal file
17
src/applications/feed/query/__init__.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/feed/storage/story');
|
||||
phutil_require_module('phabricator', 'applications/feed/storage/storyreference');
|
||||
phutil_require_module('phabricator', 'storage/qsprintf');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedQuery.php');
|
25
src/applications/feed/storage/base/PhabricatorFeedDAO.php
Normal file
25
src/applications/feed/storage/base/PhabricatorFeedDAO.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFeedDAO extends PhabricatorLiskDAO {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'feed';
|
||||
}
|
||||
|
||||
}
|
12
src/applications/feed/storage/base/__init__.php
Normal file
12
src/applications/feed/storage/base/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/base/storage/lisk');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedDAO.php');
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFeedStoryData extends PhabricatorFeedDAO {
|
||||
|
||||
protected $phid;
|
||||
|
||||
protected $storyType;
|
||||
protected $storyData;
|
||||
protected $authorPHID;
|
||||
protected $chronologicalKey;
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
self::CONFIG_SERIALIZATION => array(
|
||||
'storyData' => self::SERIALIZATION_JSON,
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function generatePHID() {
|
||||
return PhabricatorPHID::generateNewPHID(
|
||||
PhabricatorPHIDConstants::PHID_TYPE_STRY);
|
||||
}
|
||||
|
||||
}
|
14
src/applications/feed/storage/story/__init__.php
Normal file
14
src/applications/feed/storage/story/__init__.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/feed/storage/base');
|
||||
phutil_require_module('phabricator', 'applications/phid/constants');
|
||||
phutil_require_module('phabricator', 'applications/phid/storage/phid');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedStoryData.php');
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFeedStoryReference extends PhabricatorFeedDAO {
|
||||
|
||||
protected $objectPHID;
|
||||
protected $chronologicalKey;
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_IDS => self::IDS_MANUAL,
|
||||
self::CONFIG_TIMESTAMPS => false,
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
}
|
12
src/applications/feed/storage/storyreference/__init__.php
Normal file
12
src/applications/feed/storage/storyreference/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/feed/storage/base');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedStoryReference.php');
|
29
src/applications/feed/story/base/PhabricatorFeedStory.php
Normal file
29
src/applications/feed/story/base/PhabricatorFeedStory.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
abstract class PhabricatorFeedStory {
|
||||
|
||||
private $data;
|
||||
|
||||
final public function __construct(PhabricatorFeedStoryData $data) {
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
abstract public function renderView();
|
||||
|
||||
}
|
10
src/applications/feed/story/base/__init__.php
Normal file
10
src/applications/feed/story/base/__init__.php
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedStory.php');
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFeedStoryUnknown extends PhabricatorFeedStory {
|
||||
|
||||
public function renderView() {
|
||||
return new PhabricatorFeedStoryView();
|
||||
}
|
||||
|
||||
}
|
13
src/applications/feed/story/unknown/__init__.php
Normal file
13
src/applications/feed/story/unknown/__init__.php
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/feed/story/base');
|
||||
phutil_require_module('phabricator', 'applications/feed/view/story');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedStoryUnknown.php');
|
21
src/applications/feed/view/base/PhabricatorFeedView.php
Normal file
21
src/applications/feed/view/base/PhabricatorFeedView.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
abstract class PhabricatorFeedView extends AphrontView {
|
||||
|
||||
}
|
12
src/applications/feed/view/base/__init__.php
Normal file
12
src/applications/feed/view/base/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedView.php');
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorFeedStoryView extends PhabricatorFeedView {
|
||||
|
||||
public function render() {
|
||||
return phutil_render_tag(
|
||||
'div',
|
||||
array(
|
||||
'style' => 'border: 1px dashed black; '.
|
||||
'padding: 1em; margin: 1em; '.
|
||||
'background: #ffeedd;',
|
||||
),
|
||||
'This is a feed story!');
|
||||
}
|
||||
|
||||
}
|
14
src/applications/feed/view/story/__init__.php
Normal file
14
src/applications/feed/view/story/__init__.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/feed/view/base');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorFeedStoryView.php');
|
|
@ -93,6 +93,12 @@ class HeraldRuleController extends HeraldController {
|
|||
|
||||
$conditions = array();
|
||||
foreach ($data['conditions'] as $condition) {
|
||||
if ($condition === null) {
|
||||
// We manage this as a sparse array on the client, so may receive
|
||||
// NULL if conditions have been removed.
|
||||
continue;
|
||||
}
|
||||
|
||||
$obj = new HeraldCondition();
|
||||
$obj->setFieldName($condition[0]);
|
||||
$obj->setFieldCondition($condition[1]);
|
||||
|
@ -149,6 +155,11 @@ class HeraldRuleController extends HeraldController {
|
|||
|
||||
$actions = array();
|
||||
foreach ($data['actions'] as $action) {
|
||||
if ($action === null) {
|
||||
// Sparse on the client; removals can give us NULLs.
|
||||
continue;
|
||||
}
|
||||
|
||||
$obj = new HeraldAction();
|
||||
$obj->setAction($action[0]);
|
||||
|
||||
|
|
|
@ -42,40 +42,45 @@ class HeraldTranscriptController extends HeraldController {
|
|||
throw new Exception('Uknown transcript!');
|
||||
}
|
||||
|
||||
$field_names = HeraldFieldConfig::getFieldMap();
|
||||
$condition_names = HeraldConditionConfig::getConditionMap();
|
||||
$action_names = HeraldActionConfig::getActionMap();
|
||||
|
||||
require_celerity_resource('herald-test-css');
|
||||
|
||||
$filter = $this->getFilterPHIDs();
|
||||
$this->filterTranscript($xscript, $filter);
|
||||
$phids = array_merge($filter, $this->getTranscriptPHIDs($xscript));
|
||||
$phids = array_unique($phids);
|
||||
$phids = array_filter($phids);
|
||||
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||
->loadHandles();
|
||||
$this->handles = $handles;
|
||||
|
||||
$object_xscript = $xscript->getObjectTranscript();
|
||||
|
||||
$nav = $this->buildSideNav();
|
||||
|
||||
$apply_xscript_panel = $this->buildApplyTranscriptPanel(
|
||||
$xscript);
|
||||
$nav->appendChild($apply_xscript_panel);
|
||||
$object_xscript = $xscript->getObjectTranscript();
|
||||
if (!$object_xscript) {
|
||||
$notice = id(new AphrontErrorView())
|
||||
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
|
||||
->setTitle('Old Transcript')
|
||||
->appendChild(
|
||||
'<p>Details of this transcript have been garbage collected.</p>');
|
||||
$nav->appendChild($notice);
|
||||
} else {
|
||||
$filter = $this->getFilterPHIDs();
|
||||
$this->filterTranscript($xscript, $filter);
|
||||
$phids = array_merge($filter, $this->getTranscriptPHIDs($xscript));
|
||||
$phids = array_unique($phids);
|
||||
$phids = array_filter($phids);
|
||||
|
||||
$action_xscript_panel = $this->buildActionTranscriptPanel(
|
||||
$xscript);
|
||||
$nav->appendChild($action_xscript_panel);
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||
->loadHandles();
|
||||
$this->handles = $handles;
|
||||
|
||||
$object_xscript_panel = $this->buildObjectTranscriptPanel(
|
||||
$xscript);
|
||||
$nav->appendChild($object_xscript_panel);
|
||||
$apply_xscript_panel = $this->buildApplyTranscriptPanel(
|
||||
$xscript);
|
||||
$nav->appendChild($apply_xscript_panel);
|
||||
|
||||
$action_xscript_panel = $this->buildActionTranscriptPanel(
|
||||
$xscript);
|
||||
$nav->appendChild($action_xscript_panel);
|
||||
|
||||
$object_xscript_panel = $this->buildObjectTranscriptPanel(
|
||||
$xscript);
|
||||
$nav->appendChild($object_xscript_panel);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
TODO
|
||||
|
||||
$notice = null;
|
||||
if ($xscript->getDryRun()) {
|
||||
|
@ -84,30 +89,6 @@ class HeraldTranscriptController extends HeraldController {
|
|||
This was a dry run to test Herald rules, no actions were executed.
|
||||
</tools:notice>;
|
||||
}
|
||||
|
||||
if (!$object_xscript) {
|
||||
$notice =
|
||||
<x:frag>
|
||||
<tools:notice title="Old Transcript">
|
||||
Details of this transcript have been discarded. Full transcripts
|
||||
are retained for 30 days.
|
||||
</tools:notice>
|
||||
{$notice}
|
||||
</x:frag>;
|
||||
}
|
||||
|
||||
|
||||
return
|
||||
<herald:standard-page title="Transcript">
|
||||
<div style="padding: 1em;">
|
||||
<tools:side-nav items={$this->renderNavItems()}>
|
||||
{$notice}
|
||||
{$apply_xscript_markup}
|
||||
{$rule_table}
|
||||
{$object_xscript_table}
|
||||
</tools:side-nav>
|
||||
</div>
|
||||
</herald:standard-page>;
|
||||
*/
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
|
@ -264,7 +245,7 @@ class HeraldTranscriptController extends HeraldController {
|
|||
foreach ($xscript->getApplyTranscripts() as $id => $apply_xscript) {
|
||||
$rule_id = $apply_xscript->getRuleID();
|
||||
if ($filter_owned) {
|
||||
if (!$rule_xscripts[$rule_id]) {
|
||||
if (empty($rule_xscripts[$rule_id])) {
|
||||
// No associated rule so you can't own this effect.
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ phutil_require_module('phabricator', 'applications/herald/storage/transcript/bas
|
|||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/form/error');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
phutil_require_module('phabricator', 'view/layout/sidenav');
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue