Select the types of activity you want to include in your feed.
@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
···2727 'You have not configured any authentication providers yet. You '.
2828 'should add a provider (like username/password, LDAP, or GitHub '.
2929 'OAuth) so users can register and log in. You can add and configure '.
3030- 'providers using the [[%s | "Auth" application]].',
3131- '/auth/');
3030+ 'providers using the Auth Application.');
32313332 $this
3433 ->newIssue('auth.noproviders')
3534 ->setShortName(pht('No Auth Providers'))
3635 ->setName(pht('No Authentication Providers Configured'))
3737- ->setMessage($message);
3636+ ->setMessage($message)
3737+ ->addLink('/auth/', pht('Auth Application'));
3838 }
3939 }
4040}
···2020 $atom->setDocblockMetaValue('title', $title);
2121 }
22222323- // If the article has no @name, use the filename after stripping any
2323+ // If the article has no `@name`, use the filename after stripping any
2424 // extension.
2525 $name = idx($meta, 'name');
2626 if (!$name) {
···151151 if (count($docs) < count($params)) {
152152 $atom->addWarning(
153153 pht(
154154- 'This call takes %d parameters, but only %d are documented.',
155155- count($params),
156156- count($docs)));
154154+ 'This call takes %s parameter(s), but only %s are documented.',
155155+ new PhutilNumber(count($params)),
156156+ new PhutilNumber(count($docs))));
157157 }
158158 }
159159···212212 if (preg_match('/@(return|param|task|author)/', $value, $matches)) {
213213 $atom->addWarning(
214214 pht(
215215- 'Atom "%s" is preceded by a comment containing "@%s", but the '.
216216- 'comment is not a documentation comment. Documentation '.
217217- 'comments must begin with "%s", followed by a newline. Did '.
215215+ 'Atom "%s" is preceded by a comment containing `%s`, but '.
216216+ 'the comment is not a documentation comment. Documentation '.
217217+ 'comments must begin with `%s`, followed by a newline. Did '.
218218 'you mean to use a documentation comment? (As the comment is '.
219219 'not a documentation comment, it will be ignored.)',
220220 $atom->getName(),
221221- $matches[1],
221221+ '@'.$matches[1],
222222 '/**'));
223223 }
224224 }
···248248 if ($matches[1] !== $name) {
249249 $atom->addWarning(
250250 pht(
251251- 'Parameter "%s" is named "%s" in the documentation. The '.
252252- 'documentation may be out of date.',
251251+ 'Parameter "%s" is named "%s" in the documentation. '.
252252+ 'The documentation may be out of date.',
253253 $name,
254254 $matches[1]));
255255 }
···292292 if ($return) {
293293 $atom->addWarning(
294294 pht(
295295- 'Method %s has explicitly documented %s. The %s method always '.
296296- 'returns %s. Diviner documents this implicitly.',
295295+ 'Method `%s` has explicitly documented `%s`. The `%s` method '.
296296+ 'always returns `%s`. Diviner documents this implicitly.',
297297 '__construct()',
298298 '@return',
299299 '__construct()',
···2626 * Convert a long-form hash key like `ccbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaN` into
2727 * a shortened directory form, like `cc/bb/aaaaaaaaN`. In conjunction with
2828 * @{class:PhutilDirectoryKeyValueCache}, this gives us nice directories
2929- * inside .divinercache instead of a million hash files with huge names at
3030- * top level.
2929+ * inside `.divinercache` instead of a million hash files with huge names at
3030+ * the top level.
3131 */
3232 protected function getHashKey($hash) {
3333 return implode(
···66 return true;
77 }
8899- public function processRequest() {
1010- $request = $this->getRequest();
1111- $viewer = $request->getUser();
99+ public function handleRequest(AphrontRequest $request) {
1010+ $viewer = $request->getViewer();
12111313- $book_name = $request->getStr('book');
1212+ $book_name = $request->getStr('book');
1413 $query_text = $request->getStr('name');
15141615 $book = null;
···1918 ->setViewer($viewer)
2019 ->withNames(array($book_name))
2120 ->executeOne();
2121+2222 if (!$book) {
2323 return new Aphront404Response();
2424 }
···7070 ->setTitle(pht('Documentation Not Found'))
7171 ->appendChild(
7272 pht(
7373- 'Unable to find the specified documentation. You may have '.
7474- 'followed a bad or outdated link.'))
7373+ 'Unable to find the specified documentation. '.
7474+ 'You may have followed a bad or outdated link.'))
7575 ->addCancelButton($not_found_uri, pht('Read More Documentation'));
76767777 return id(new AphrontDialogResponse())->setDialog($dialog);
···66 return true;
77 }
8899- public function processRequest() {
1010- $request = $this->getRequest();
1111- $viewer = $request->getUser();
99+ public function handleRequest(AphrontRequest $request) {
1010+ $viewer = $request->getViewer();
12111312 $books = id(new DivinerBookQuery())
1413 ->setViewer($viewer)
···5352 ->appendChild($list);
54535554 $document->appendChild($list);
5656-5755 } else {
5856 $text = pht(
5959- "(NOTE) **Looking for Phabricator documentation?** If you're looking ".
6060- "for help and information about Phabricator, you can ".
6161- "[[ https://secure.phabricator.com/diviner/ | browse the public ".
6262- "Phabricator documentation ]] on the live site.\n\n".
6363- "Diviner is the documentation generator used to build the Phabricator ".
6464- "documentation.\n\n".
5757+ "(NOTE) **Looking for Phabricator documentation?** ".
5858+ "If you're looking for help and information about Phabricator, ".
5959+ "you can [[https://secure.phabricator.com/diviner/ | ".
6060+ "browse the public Phabricator documentation]] on the live site.\n\n".
6161+ "Diviner is the documentation generator used to build the ".
6262+ "Phabricator documentation.\n\n".
6563 "You haven't generated any Diviner documentation books yet, so ".
6664 "there's nothing to show here. If you'd like to generate your own ".
6765 "local copy of the Phabricator documentation and have it appear ".
6866 "here, run this command:\n\n".
6969- " phabricator/ $ ./bin/diviner generate\n\n".
7070- "Right now, Diviner isn't very useful for generating documentation ".
7171- "for projects other than Phabricator. If you're interested in using ".
7272- "it in your own projects, leave feedback for us on ".
7373- "[[ https://secure.phabricator.com/T4558 | T4558 ]].");
6767+ " %s\n\n",
6868+ 'phabricator/ $ ./bin/diviner generate');
74697570 $text = PhabricatorMarkupEngine::renderOneObject(
7671 id(new PhabricatorMarkupOneOff())->setContent($text),
···7979 return $this;
8080 }
81818282-8382 /**
8483 * Include or exclude "ghosts", which are symbols which used to exist but do
8584 * not exist currently (for example, a function which existed in an older
···137136 foreach ($atoms as $key => $atom) {
138137 $book = idx($books, $atom->getBookPHID());
139138 if (!$book) {
139139+ $this->didRejectResult($atom);
140140 unset($atoms[$key]);
141141 continue;
142142 }
···158158 // Load all of the symbols this symbol extends, recursively. Commonly,
159159 // this means all the ancestor classes and interfaces it extends and
160160 // implements.
161161-162161 if ($this->needExtends) {
163163-164162 // First, load all the matching symbols by name. This does 99% of the
165163 // work in most cases, assuming things are named at all reasonably.
166166-167164 $names = array();
168165 foreach ($atoms as $atom) {
169166 if (!$atom->getAtom()) {
···303300304301 if ($this->titles) {
305302 $hashes = array();
303303+306304 foreach ($this->titles as $title) {
307305 $slug = DivinerAtomRef::normalizeTitleString($title);
308306 $hash = PhabricatorHash::digestForIndex($slug);
···318316 if ($this->contexts) {
319317 $with_null = false;
320318 $contexts = $this->contexts;
319319+321320 foreach ($contexts as $key => $value) {
322321 if ($value === null) {
323322 unset($contexts[$key]);
···373372 }
374373375374 if ($this->nameContains) {
376376- // NOTE: This CONVERT() call makes queries case-insensitive, since the
377377- // column has binary collation. Eventually, this should move into
375375+ // NOTE: This `CONVERT()` call makes queries case-insensitive, since
376376+ // the column has binary collation. Eventually, this should move into
378377 // fulltext.
379379-380378 $where[] = qsprintf(
381379 $conn_r,
382380 'CONVERT(name USING utf8) LIKE %~',
···387385388386 return $this->formatWhereClause($where);
389387 }
390390-391388392389 /**
393390 * Walk a list of atoms and collect all the node hashes of the atoms'
···413410 foreach ($child_hashes as $hash) {
414411 $hashes[$hash] = $hash;
415412 }
413413+416414 if ($recurse_up) {
417415 $hashes += $this->getAllChildHashes($symbol->getExtends(), true);
418416 }
···420418421419 return $hashes;
422420 }
423423-424421425422 /**
426423 * Attach child atoms to existing atoms. In recursive mode, also attach child
···452449 $symbol_children[] = $children[$hash];
453450 }
454451 }
452452+455453 $symbol->attachChildren($symbol_children);
454454+456455 if ($recurse_up) {
457456 $this->attachAllChildren($symbol->getExtends(), $children, true);
458457 }
···11+<?php
22+33+final class DivinerLiveBookTransactionQuery
44+ extends PhabricatorApplicationTransactionQuery {
55+66+ public function getTemplateApplicationTransaction() {
77+ return new DivinerLiveBookTransaction();
88+ }
99+1010+}
···202202 }
203203204204 if ($ref->getBook() != $this->getConfig('name')) {
205205- // If the ref is from a different book, we can't normalize it. Just return
206206- // it as-is if it has enough information to resolve.
205205+ // If the ref is from a different book, we can't normalize it.
206206+ // Just return it as-is if it has enough information to resolve.
207207 if ($ref->getName() && $ref->getType()) {
208208 return $ref;
209209 } else {
···259259 ),
260260 $ref->getTitle());
261261 }
262262-263262264263}
···137137 }
138138139139 public function save() {
140140-141140 // NOTE: The identity hash is just a sanity check because the unique tuple
142142- // on this table is way way too long to fit into a normal UNIQUE KEY. We
143143- // don't use it directly, but its existence prevents duplicate records.
141141+ // on this table is way way too long to fit into a normal `UNIQUE KEY`.
142142+ // We don't use it directly, but its existence prevents duplicate records.
144143145144 if (!$this->identityHash) {
146145 $this->identityHash = PhabricatorHash::digestForIndex(
···159158160159 public function getTitle() {
161160 $title = parent::getTitle();
161161+162162 if (!strlen($title)) {
163163 $title = $this->getName();
164164 }
165165+165166 return $title;
166167 }
167168168169 public function setTitle($value) {
169170 $this->writeField('title', $value);
171171+170172 if (strlen($value)) {
171173 $slug = DivinerAtomRef::normalizeTitleString($value);
172174 $hash = PhabricatorHash::digestForIndex($slug);
···174176 } else {
175177 $this->titleSlugHash = null;
176178 }
179179+177180 return $this;
178181 }
179182···199202200203201204/* -( PhabricatorPolicyInterface )----------------------------------------- */
205205+202206203207 public function getCapabilities() {
204208 return $this->getBook()->getCapabilities();
205209 }
206210207207-208211 public function getPolicy($capability) {
209212 return $this->getBook()->getPolicy($capability);
210213 }
211211-212214213215 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
214216 return $this->getBook()->hasAutomaticCapability($capability, $viewer);
···219221 }
220222221223222222-/* -( Markup Interface )--------------------------------------------------- */
224224+/* -( PhabricatorMarkupInterface )------------------------------------------ */
223225224226225227 public function getMarkupFieldKey($field) {
226228 return $this->getPHID().':'.$field.':'.$this->getGraphHash();
227229 }
228230229229-230231 public function newMarkupEngine($field) {
231232 return PhabricatorMarkupEngine::getEngine('diviner');
232233 }
233233-234234235235 public function getMarkupText($field) {
236236 if (!$this->getAtom()) {
···240240 return $this->getAtom()->getDocblockText();
241241 }
242242243243-244244- public function didMarkupText(
245245- $field,
246246- $output,
247247- PhutilMarkupEngine $engine) {
243243+ public function didMarkupText($field, $output, PhutilMarkupEngine $engine) {
248244 return $output;
249245 }
250246251251-252247 public function shouldUseMarkupCache($field) {
253248 return true;
254249 }
255250251251+256252/* -( PhabricatorDestructibleInterface )----------------------------------- */
253253+257254258255 public function destroyObjectPermanently(
259256 PhabricatorDestructionEngine $engine) {
···36363737 $atomizer_class = $args->getArg('atomizer');
3838 if (!$atomizer_class) {
3939- throw new Exception(
4040- pht('Specify an atomizer class with %s.', '--atomizer'));
3939+ throw new PhutilArgumentUsageException(
4040+ pht(
4141+ 'Specify an atomizer class with %s.',
4242+ '--atomizer'));
4143 }
42444345 $symbols = id(new PhutilSymbolLoader())
···4648 ->setAncestorClass('DivinerAtomizer')
4749 ->selectAndLoadSymbols();
4850 if (!$symbols) {
4949- throw new Exception(
5151+ throw new PhutilArgumentUsageException(
5052 pht(
5153 "Atomizer class '%s' must be a concrete subclass of %s.",
5254 $atomizer_class,
···4747 $is_new = true;
48484949 // Prefill username if provided.
5050- $credential->setUsername($request->getStr('username'));
5050+ $credential->setUsername((string)$request->getStr('username'));
51515252 if (!$request->getStr('isInitialized')) {
5353 $type->didInitializeNewCredential($viewer, $credential);
···151151 $credential->openTransaction();
152152153153 if (!$credential->getIsLocked()) {
154154- $xactions[] = id(new PassphraseCredentialTransaction())
154154+ if ($type->shouldRequireUsername()) {
155155+ $xactions[] = id(new PassphraseCredentialTransaction())
155156 ->setTransactionType($type_username)
156157 ->setNewValue($v_username);
157157-158158+ }
158159 // If some value other than a sequence of bullets was provided for
159160 // the credential, update it. In particular, note that we are
160161 // explicitly allowing empty secrets: one use case is HTTP auth where
···263264 pht('This credential is permanently locked and can not be edited.'));
264265 }
265266266266- $form
267267+ if ($type->shouldRequireUsername()) {
268268+ $form
267269 ->appendChild(
268270 id(new AphrontFormTextControl())
269271 ->setName('username')
270272 ->setLabel(pht('Login/Username'))
271273 ->setValue($v_username)
272274 ->setDisabled($credential_is_locked)
273273- ->setError($e_username))
274274- ->appendChild(
275275+ ->setError($e_username));
276276+ }
277277+ $form
278278+ ->appendChild(
275279 $secret_control
276280 ->setName('secret')
277281 ->setLabel($type->getSecretLabel())
···3636 // about it.
3737 if (strlen($v_slug)) {
3838 $normal_slug = PhabricatorSlug::normalize($v_slug);
3939- if ($normal_slug !== $v_slug) {
3939+ $no_slash_slug = rtrim($normal_slug, '/');
4040+ if ($normal_slug !== $v_slug && $no_slash_slug !== $v_slug) {
4041 return $this->newDialog()
4142 ->setTitle(pht('Adjust Path'))
4243 ->appendParagraph(
4344 pht(
4445 'The path you entered (%s) is not a valid wiki document '.
4545- 'path. Paths may not contain special characters.',
4646+ 'path. Paths may not contain spaces or special characters.',
4647 phutil_tag('strong', array(), $v_slug)))
4748 ->appendParagraph(
4849 pht(