From 83edbffd521d315399892f2c665b5f174d68dc6a Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Sat, 10 Jun 2023 11:54:16 +0200 Subject: [PATCH 01/82] Config page: add lovely git-related error messages in standard error log Summary: Premise: the Config page runs git commands. Spoiler: they can fail. Before this change errors were just suppressed and ignored. After this change you get at least a log line. Also, you get a tip for a very specific well-known error affecting recent git. Probably suppressing stuff was fine in the moment git worked here. But nowadays git doesn't work so easily here, since it introduced very weird additional configurations in order for a repository to be indicated as "safe" or not. Error suppression was a problem there, because understanding the error with "future objects" is not trivial for most users. Really. After this change, these errors are beautifully mentioned in the standard log of your webserver, to the best of our communication ability. This is a cute example of a new log line: Cannot identify the version of the phorge repository because the webserver does not trust it (more info on Task https://we.phorge.it/T15282). Try this system resolution: sudo git config --system --add safe.directory /var/www/phorge Another: Cannot identify the version of the phorge repository because the webserver does not trust it (more info on Task https://we.phorge.it/T15282). Try this system resolution: sudo git config --system --add safe.directory /var/www/arcanist Incidentally, these specific errors probably afflict your Phorge/Phabricator, and now you have some useful resolution tips. You are welcome! You can also join T15282 to discuss your specific case. Closes T15243 Test Plan: - visit the `/config/` page: does it worked before? it still works now - visit the `/config/` page without `/etc/gitconfig`: you may still see "Unknown" as version - but, you finally get something in the log (instead of nothing) - visit the `/config/` page after following your log messages: now you should see the library versions! yeeh Additional tests: - manually sabotage the command "git log" replacing with "gitfooolog" and visit /config page: see the unexpected 'gitfooolog command not found' log line - manually sabotage the command "git remove" replacing with "gitremotelog" and visit /config/ page: see the unexpected 'gitremotelog command not found' log line Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: avivey, deadalnix, aklapper, speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15243 Differential Revision: https://we.phorge.it/D25148 --- .../PhabricatorConfigConsoleController.php | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/applications/config/controller/PhabricatorConfigConsoleController.php b/src/applications/config/controller/PhabricatorConfigConsoleController.php index f70398bc5f..e545019666 100644 --- a/src/applications/config/controller/PhabricatorConfigConsoleController.php +++ b/src/applications/config/controller/PhabricatorConfigConsoleController.php @@ -189,9 +189,10 @@ final class PhabricatorConfigConsoleController foreach ($specs as $lib) { $remote_future = $remote_futures[$lib]; - list($err, $stdout) = $remote_future->resolve(); - if ($err) { - // If this fails for whatever reason, just move on. + try { + list($stdout, $err) = $remote_future->resolvex(); + } catch (CommandException $e) { + $this->logGitErrorWithPotentialTips($e, $lib); continue; } @@ -258,13 +259,14 @@ final class PhabricatorConfigConsoleController $results = array(); foreach ($log_futures as $lib => $future) { - list($err, $stdout) = $future->resolve(); - if (!$err) { + try { + list($stdout, $err) = $future->resolvex(); list($hash, $epoch) = explode(' ', $stdout); - } else { + } catch (CommandException $e) { $hash = null; $epoch = null; - } + $this->logGitErrorWithPotentialTips($e, $lib); + } $result = array( 'hash' => $hash, @@ -275,7 +277,7 @@ final class PhabricatorConfigConsoleController $upstream_future = idx($upstream_futures, $lib); if ($upstream_future) { - list($err, $stdout) = $upstream_future->resolve(); + list($stdout, $err) = $upstream_future->resolvex(); if (!$err) { $branchpoint = trim($stdout); if (strlen($branchpoint)) { @@ -340,5 +342,36 @@ final class PhabricatorConfigConsoleController ->appendChild($table_view); } + /** + * Help in better troubleshooting git errors. + * @param CommandException $e Exception + * @param string $lib Library name involved + */ + private function logGitErrorWithPotentialTips($e, $lib) { + + // First, detect this specific error message related to [safe] stuff. + $expected_error_msg_part = 'detected dubious ownership in repository'; + $stderr = $e->getStderr(); + if (strpos($stderr, $expected_error_msg_part) !== false) { + + // Found! Let's show a nice resolution tip. + + // Complete path of the problematic repository. + $lib_root = dirname(phutil_get_library_root($lib)); + + phlog(pht( + "Cannot identify the version of the %s repository because ". + "the webserver does not trust it (more info on Task %s).\n". + "Try this system resolution:\n". + "sudo git config --system --add safe.directory %s", + $lib, + 'https://we.phorge.it/T15282', + $lib_root)); + } else { + + // Otherwise show a generic error message + phlog($e); + } + } } From bab99707405585911ca0e07d52d7117acd08fbcc Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Sat, 10 Jun 2023 16:25:56 +0200 Subject: [PATCH 02/82] Fix PHP 8.1 "trim(null)" exception which blocks rendering Conduit's harbormaster.sendmessage page Summary: Since PHP 8.1, passing a null string to `trim()` is deprecated. Thus first check that `$content` is not null before trimming it. Also since trim() returns a string and never null, we can also simplify the non-empty check, in a more readable and efficient way, avoiding strlen() that was usually used for other "more wild" cases. ``` EXCEPTION: (RuntimeException) trim(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=18554ea76ceb), phorge(head=master, ref.master=0d81da590923) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/error/PhutilErrorHandler.php:261] #1 <#2> trim(NULL) called at [/src/infrastructure/markup/blockrule/PhutilRemarkupTableBlockRule.php:117] ``` Closes T15427 Test Plan: Applied this change, afterwards `/conduit/method/harbormaster.sendmessage/` correctly rendered in web browser. Reviewers: O1 Blessed Committers, speck, valerio.bozzolan Reviewed By: O1 Blessed Committers, speck, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15427 Differential Revision: https://we.phorge.it/D25259 --- .../markup/blockrule/PhutilRemarkupTableBlockRule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/infrastructure/markup/blockrule/PhutilRemarkupTableBlockRule.php b/src/infrastructure/markup/blockrule/PhutilRemarkupTableBlockRule.php index 72e61881ce..f02b9b7422 100644 --- a/src/infrastructure/markup/blockrule/PhutilRemarkupTableBlockRule.php +++ b/src/infrastructure/markup/blockrule/PhutilRemarkupTableBlockRule.php @@ -114,7 +114,7 @@ final class PhutilRemarkupTableBlockRule extends PhutilRemarkupBlockRule { if ($cell->isContentNode()) { $content = $node->getContent(); - if (!strlen(trim($content))) { + if ($content === null || trim($content) === '') { continue; } From 76ef9db8a5ed652b5d74f6a85031e1292a897837 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Sat, 10 Jun 2023 18:33:58 +0200 Subject: [PATCH 03/82] Fix PHP 8.1 "strlen(null)" exception about Staging URI on Diffusion repo History page Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. Passing null to strlen() is deprecated since PHP 8.1. Thus first check that the string is not null. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=b325304b6e52), phorge(head=master, ref.master=83edbffd521d) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/repository/xaction/PhabricatorRepositoryStagingURITransaction.php:20] ``` This is quite similar to D25277. Closes T15458 Test Plan: After applying this change, editing the Staging URI by saving its already empty value, and going to the repo History page, the page `/diffusion/1/manage/history/` renders without an exception, showing `R1` being Inactive and `user set as the staging area for this repository.` [sic!] Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15458 Differential Revision: https://we.phorge.it/D25282 --- .../xaction/PhabricatorRepositoryStagingURITransaction.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/repository/xaction/PhabricatorRepositoryStagingURITransaction.php b/src/applications/repository/xaction/PhabricatorRepositoryStagingURITransaction.php index 4297d5e244..ed50f65e4e 100644 --- a/src/applications/repository/xaction/PhabricatorRepositoryStagingURITransaction.php +++ b/src/applications/repository/xaction/PhabricatorRepositoryStagingURITransaction.php @@ -17,12 +17,12 @@ final class PhabricatorRepositoryStagingURITransaction $old = $this->getOldValue(); $new = $this->getNewValue(); - if (!strlen($old)) { + if ($old === null || !strlen($old)) { return pht( '%s set %s as the staging area for this repository.', $this->renderAuthor(), $this->renderNewValue()); - } else if (!strlen($new)) { + } else if ($new === null || !strlen($new)) { return pht( '%s removed %s as the staging area for this repository.', $this->renderAuthor(), From b4cfe56f03b44615ac9251aed8d74bf13b085051 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Sat, 10 Jun 2023 18:40:00 +0200 Subject: [PATCH 04/82] Fix PHP 8.1 "ltrim(null)" exception which blocks rendering first Meme comment Summary: Since PHP 8.1, passing a null string to `ltrim(string $string)` is deprecated. Thus first check if After and Below text are not null before trimming. Closes T15379 Test Plan: Applied this change; afterwards several times created a new Pholio mock and added a Meme comment. I could not reproduce the problem anymore (first meme comment in a mock always rendered correctly instead of showing an exception as comment). However, I could not reliably reproduce the problem anyway. - Create a meme without any above/below text - Create a meme with just spaces as above/below text - Create a meme with just above text as "asd", or "0" or a lizard - Create a meme with just below text as "asd", or "0" or a lizard - Create a meme with both above and below texts with "asd", "0" and a lizard and more stuff (doing all 64 combinations) Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15379 Differential Revision: https://we.phorge.it/D25212 --- src/applications/macro/engine/PhabricatorMemeEngine.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/applications/macro/engine/PhabricatorMemeEngine.php b/src/applications/macro/engine/PhabricatorMemeEngine.php index afee0f9b18..e1befc20a2 100644 --- a/src/applications/macro/engine/PhabricatorMemeEngine.php +++ b/src/applications/macro/engine/PhabricatorMemeEngine.php @@ -182,7 +182,8 @@ final class PhabricatorMemeEngine extends Phobject { // changes to the image. $above_text = $this->getAboveText(); $below_text = $this->getBelowText(); - if (!strlen(trim($above_text)) && !strlen(trim($below_text))) { + if (($above_text === null || !phutil_nonempty_string(trim($above_text))) && + ($below_text === null || !phutil_nonempty_string(trim($below_text)))) { return $template_data; } From c553692d452b764d2877469c5639812384634828 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Sat, 10 Jun 2023 22:58:10 +0200 Subject: [PATCH 05/82] Fix PHP 8.1 "strlen(null)" exception which blocks rendering errors on Create Blueprint page Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=e4fd31ec024e), phorge(head=D25240, ref.master=b1edfea09bad, ref.D25240=b1edfea09bad) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php:392] ``` Closes T15413 Test Plan: Applied this change on top of D25239. Afterwards, the "Create Blueprint" page on `/drydock/blueprint/edit/form/default/` after pressing the "Create Blueprint" button the page correctly renders the expected error that some fields cannot be empty. # Enter a commit message. # # Changes: # # src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php Also, try to create extra numeric fields (like in the User application) and try to send zero or 1 using Conduit `user.edit`. Reviewers: O1 Blessed Committers, valerio.bozzolan, speck Reviewed By: O1 Blessed Committers, valerio.bozzolan, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15413 Differential Revision: https://we.phorge.it/D25240 --- .../customfield/standard/PhabricatorStandardCustomField.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php index 4c0bce861b..c41148a4aa 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php @@ -389,7 +389,7 @@ abstract class PhabricatorStandardCustomField if (is_array($value)) { return empty($value); } - return !strlen($value); + return $value === null || !strlen($value); } public function getApplicationTransactionTitle( From 7b57ba2b982f9d4376a876717d7ae76b8d880820 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Sat, 10 Jun 2023 22:59:07 +0200 Subject: [PATCH 06/82] Fix PHP 8.1 "strlen(null)" exception initializing Diffusion repository without path access permissions Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. Closes T15459 Test Plan: After applying this change, going to `/diffusion/17/manage/`, the actual error (`cannot mkdir /var/repo/17: Permission denied`) is propagated and displayed in the "Working Copy Status" section, instead of being hidden by a `strlen()` exception. See T15459 for details. Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15459 Differential Revision: https://we.phorge.it/D25283 --- src/applications/repository/storage/PhabricatorRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php index b05be618c0..eb57b31b57 100644 --- a/src/applications/repository/storage/PhabricatorRepository.php +++ b/src/applications/repository/storage/PhabricatorRepository.php @@ -1160,7 +1160,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO */ public function getRemoteURIObject() { $raw_uri = $this->getDetail('remote-uri'); - if (!strlen($raw_uri)) { + if (!phutil_nonempty_string($raw_uri)) { return new PhutilURI(''); } From 108cbcd09bd39fda0ad24a2ee25afe5aac230e08 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Sun, 11 Jun 2023 16:33:20 +0200 Subject: [PATCH 07/82] Fix PHP 8.1 "base64_decode(null)" exception calling Conduit's file.upload with no data passed Summary: Since PHP 8.1, `base64_decode()` does not accept passing null as a parameter. Thus first check that `data !== null` before calling `decodeBase64($data)` (which then calls PHP's `base64_decode()`), and throw an exception if it is. ``` EXCEPTION: (RuntimeException) base64_decode(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=18554ea76ceb), phorge(head=conduitDashboardPanelEdit, ref.master=0d81da590923, ref.conduitDashboardPanelEdit=ab4391b30465) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/error/PhutilErrorHandler.php:261] #1 <#2> base64_decode(NULL, boolean) called at [/src/applications/files/conduit/FileConduitAPIMethod.php:84] ``` Closes T15426 Test Plan: Applied this change; afterwards `/api/file.upload` under "Method Result", "error_info" shows "Unable to decode base64 data!" instead of "base64_decode(): Passing null to parameter #1 ($string) of type string is deprecated" which is more descriptive. Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15426 Differential Revision: https://we.phorge.it/D25258 --- src/applications/files/conduit/FileUploadConduitAPIMethod.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/applications/files/conduit/FileUploadConduitAPIMethod.php b/src/applications/files/conduit/FileUploadConduitAPIMethod.php index 8b3b9faaaa..cafe842596 100644 --- a/src/applications/files/conduit/FileUploadConduitAPIMethod.php +++ b/src/applications/files/conduit/FileUploadConduitAPIMethod.php @@ -31,8 +31,10 @@ final class FileUploadConduitAPIMethod extends FileConduitAPIMethod { $view_policy = $request->getValue('viewPolicy'); $data = $request->getValue('data_base64'); + if (!phutil_nonempty_string($data)) { + throw new Exception(pht('Field "data_base64" must be non-empty.')); + } $data = $this->decodeBase64($data); - $params = array( 'authorPHID' => $viewer->getPHID(), 'canCDN' => $can_cdn, From 9b99123ff93120f78d2eaafe6f830fcec5a4e7ef Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 12 Jun 2023 02:33:37 +0200 Subject: [PATCH 08/82] Fix PHP 8.1 "strlen(null)" exceptions trying to browse Diffusion repository history Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=diffusionBrowseCode, ref.master=108cbcd09bd3, ref.diffusionBrowseCode=015ffef14b0c) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/diffusion/conduit/DiffusionHistoryQueryConduitAPIMethod.php:50] ``` ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=diffusionBrowseCode, ref.master=108cbcd09bd3, ref.diffusionBrowseCode=015ffef14b0c) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/diffusion/conduit/DiffusionHistoryQueryConduitAPIMethod.php:50] ``` Closes T15463 Test Plan: After applying these two changes, get next expected exceptions about `RuntimeException: file_exists(): Passing null to parameter #1 ($filename) of type string is deprecated` and `CommandException: Command failed with error #128! fatal: detected dubious ownership in repository at '/var/repo/1'`, but no RuntimeException about `strlen()` anymore. Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15463 Differential Revision: https://we.phorge.it/D25287 --- .../conduit/DiffusionHistoryQueryConduitAPIMethod.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/diffusion/conduit/DiffusionHistoryQueryConduitAPIMethod.php b/src/applications/diffusion/conduit/DiffusionHistoryQueryConduitAPIMethod.php index 5eb20d2f7e..ba0ee3bd0b 100644 --- a/src/applications/diffusion/conduit/DiffusionHistoryQueryConduitAPIMethod.php +++ b/src/applications/diffusion/conduit/DiffusionHistoryQueryConduitAPIMethod.php @@ -47,14 +47,14 @@ final class DiffusionHistoryQueryConduitAPIMethod $against_hash = $request->getValue('against'); $path = $request->getValue('path'); - if (!strlen($path)) { + if (!phutil_nonempty_string($path)) { $path = null; } $offset = $request->getValue('offset'); $limit = $request->getValue('limit'); - if (strlen($against_hash)) { + if (phutil_nonempty_string($against_hash)) { $commit_range = "{$against_hash}..{$commit_hash}"; } else { $commit_range = $commit_hash; From 331b9cca42600e6e758e6c3c6d9c8456ab606913 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 12 Jun 2023 03:36:56 +0200 Subject: [PATCH 09/82] Fix PHP 8.1 "strlen(null)" exception rendering a commit in Diffusion when bugtraq.url = null Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=diffusionBrowseCommit, ref.master=9b99123ff931, ref.diffusionBrowseCommit=9b99123ff931) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/diffusion/controller/DiffusionCommitController.php:925] ``` Closes T15464 Test Plan: After applying this change, selecting the last commit on http://phorge.localhost/diffusion/query/all/ correctly renders the commit page (e.g. `/R1:1234567890abcdef1234567890abcdef12345678`) Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15464 Differential Revision: https://we.phorge.it/D25288 --- .../diffusion/controller/DiffusionCommitController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/diffusion/controller/DiffusionCommitController.php b/src/applications/diffusion/controller/DiffusionCommitController.php index 7b893b1e52..ef469281ef 100644 --- a/src/applications/diffusion/controller/DiffusionCommitController.php +++ b/src/applications/diffusion/controller/DiffusionCommitController.php @@ -922,7 +922,7 @@ final class DiffusionCommitController extends DiffusionController { private function linkBugtraq($corpus) { $url = PhabricatorEnv::getEnvConfig('bugtraq.url'); - if (!strlen($url)) { + if (!phutil_nonempty_string($url)) { return $corpus; } From db19b23dce9a12d8ba68f9c179a6e4ce1a336f34 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 12 Jun 2023 03:49:19 +0200 Subject: [PATCH 10/82] Fix PHP 8.1 "strlen(null)" exceptions on History page of Diffusion repo after changing text encoding Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=master, ref.master=108cbcd09bd3) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/repository/xaction/PhabricatorRepositoryEncodingTransaction.php:20] ``` Closes T15460 Test Plan: After applying these two changes, changing the text encoding of a Diffusion repository to a valid encoding and going to `/diffusion/1/manage/history/`, page renders correctly and shows no exception. Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15460 Differential Revision: https://we.phorge.it/D25284 --- .../xaction/PhabricatorRepositoryEncodingTransaction.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/repository/xaction/PhabricatorRepositoryEncodingTransaction.php b/src/applications/repository/xaction/PhabricatorRepositoryEncodingTransaction.php index ef129da832..203b98abec 100644 --- a/src/applications/repository/xaction/PhabricatorRepositoryEncodingTransaction.php +++ b/src/applications/repository/xaction/PhabricatorRepositoryEncodingTransaction.php @@ -17,12 +17,12 @@ final class PhabricatorRepositoryEncodingTransaction $old = $this->getOldValue(); $new = $this->getNewValue(); - if (strlen($old) && !strlen($new)) { + if ($old !== null && $new === null) { return pht( '%s removed the %s encoding configured for this repository.', $this->renderAuthor(), $this->renderOldValue()); - } else if (strlen($new) && !strlen($old)) { + } else if ($new !== null && $old === null) { return pht( '%s set the encoding for this repository to %s.', $this->renderAuthor(), From 32b2d3871f722123d6c6eac604786048e7a315bb Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 12 Jun 2023 03:49:51 +0200 Subject: [PATCH 11/82] Fix PHP 8.1 "strlen(null)" exceptions trying to browse Diffusion repository code Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=diffusionBrowseCode, ref.master=108cbcd09bd3, ref.diffusionBrowseCode=108cbcd09bd3) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/diffusion/controller/DiffusionBrowseController.php:25] ``` ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=diffusionBrowseCode, ref.master=108cbcd09bd3, ref.diffusionBrowseCode=108cbcd09bd3) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/diffusion/conduit/DiffusionBrowseQueryConduitAPIMethod.php:40] ``` Closes T15462 Test Plan: After applying these two changes, get next expected exceptions about `RuntimeException: file_exists(): Passing null to parameter #1 ($filename) of type string is deprecated` and `CommandException: Command failed with error #128! fatal: detected dubious ownership in repository at '/var/repo/1'`, but no RuntimeException about `strlen()` anymore. Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15462 Differential Revision: https://we.phorge.it/D25286 --- .../diffusion/conduit/DiffusionBrowseQueryConduitAPIMethod.php | 2 +- .../diffusion/controller/DiffusionBrowseController.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/diffusion/conduit/DiffusionBrowseQueryConduitAPIMethod.php b/src/applications/diffusion/conduit/DiffusionBrowseQueryConduitAPIMethod.php index 86ec7b7466..80c3f7b27d 100644 --- a/src/applications/diffusion/conduit/DiffusionBrowseQueryConduitAPIMethod.php +++ b/src/applications/diffusion/conduit/DiffusionBrowseQueryConduitAPIMethod.php @@ -37,7 +37,7 @@ final class DiffusionBrowseQueryConduitAPIMethod $repository = $drequest->getRepository(); $path = $request->getValue('path'); - if (!strlen($path) || $path === '/') { + if (!phutil_nonempty_string($path) || $path === '/') { $path = null; } diff --git a/src/applications/diffusion/controller/DiffusionBrowseController.php b/src/applications/diffusion/controller/DiffusionBrowseController.php index 2b81ab89cc..b81c42db8c 100644 --- a/src/applications/diffusion/controller/DiffusionBrowseController.php +++ b/src/applications/diffusion/controller/DiffusionBrowseController.php @@ -22,7 +22,7 @@ final class DiffusionBrowseController extends DiffusionController { // list. $grep = $request->getStr('grep'); - if (strlen($grep)) { + if (phutil_nonempty_string($grep)) { return $this->browseSearch(); } From efbb809d420f9328c3fd451404d5b9881fa73178 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 12 Jun 2023 11:20:52 +0200 Subject: [PATCH 12/82] Fix PHP 8.1 "strlen(null)" exception which blocks rendering commit page in Diffusion Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=diffusionCallsignHistory, ref.master=9b99123ff931, ref.diffusionCallsignHistory=d5fb6702a49a) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/diffusion/controller/DiffusionCommitController.php:31] ``` Closes T15466 Test Plan: After applying this change, going to an existing commit URL like `/diffusion/XYZ/commit/999a2c7d1ff8` shows the exception covered by T15464 instead, as expected. Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15466 Differential Revision: https://we.phorge.it/D25290 --- .../diffusion/controller/DiffusionCommitController.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/applications/diffusion/controller/DiffusionCommitController.php b/src/applications/diffusion/controller/DiffusionCommitController.php index ef469281ef..ce3ef41c9e 100644 --- a/src/applications/diffusion/controller/DiffusionCommitController.php +++ b/src/applications/diffusion/controller/DiffusionCommitController.php @@ -27,8 +27,9 @@ final class DiffusionCommitController extends DiffusionController { // If this page is being accessed via "/source/xyz/commit/...", redirect // to the canonical URI. - $has_callsign = strlen($request->getURIData('repositoryCallsign')); - $has_id = strlen($request->getURIData('repositoryID')); + $has_callsign = + phutil_nonempty_string($request->getURIData('repositoryCallsign')); + $has_id = phutil_nonempty_string($request->getURIData('repositoryID')); if (!$has_callsign && !$has_id) { $canonical_uri = $repository->getCommitURI($commit_identifier); return id(new AphrontRedirectResponse()) From 1060736e895b7761fbcc1653635f82bbfd3ca94e Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 12 Jun 2023 17:28:16 +0200 Subject: [PATCH 13/82] Fix some icons not displayed on UIExamples' "Icons and Images" (PHUIIconExample) page Summary: Fix three typos in icon names Closes T15454 Test Plan: Go to `/uiexample/view/PHUIIconExample/` before and after applying the change; compare icons displayed for `fa-codiepie`, `fa-user-o`, `fa-thermometer-0` Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15454 Differential Revision: https://we.phorge.it/D25280 --- src/view/phui/PHUIIconView.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/view/phui/PHUIIconView.php b/src/view/phui/PHUIIconView.php index a5897e02d6..5a6bba71b1 100644 --- a/src/view/phui/PHUIIconView.php +++ b/src/view/phui/PHUIIconView.php @@ -780,7 +780,7 @@ final class PHUIIconView extends AphrontTagView { 'fa-reddit-alien', 'fa-edge', 'fa-credit-card-alt', - 'fa-codiepie:before', + 'fa-codiepie', 'fa-modx', 'fa-fort-awesome', 'fa-usb', @@ -843,7 +843,7 @@ final class PHUIIconView extends AphrontTagView { 'fa-address-card-o', 'fa-user-circle', 'fa-user-circle-o', - 'fa-user-o:before', + 'fa-user-o', 'fa-id-badge', 'fa-drivers-license', 'fa-id-card', @@ -861,7 +861,7 @@ final class PHUIIconView extends AphrontTagView { 'fa-thermometer-half', 'fa-thermometer-1', 'fa-thermometer-quarter', - 'fa-thermometer-0:', + 'fa-thermometer-0', 'fa-thermometer-empty', 'fa-shower', 'fa-bathtub', From 3f8846d80c53f678c764381378153f216be61a37 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 12 Jun 2023 21:47:30 +0200 Subject: [PATCH 14/82] Fix PHP 8.1 "strlen(null)" exception on Diffusion repository History page after setting Callsign Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=diffusionCallsignHistory, ref.master=9b99123ff931, ref.diffusionCallsignHistory=9b99123ff931) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/repository/xaction/PhabricatorRepositoryCallsignTransaction.php:28] ``` Closes T15465 Test Plan: After applying this change, `/diffusion/XYZ/manage/history/` renders correctly and shows `user set the callsign for this repository to XYZ.` Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15465 Differential Revision: https://we.phorge.it/D25289 --- .../xaction/PhabricatorRepositoryCallsignTransaction.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/repository/xaction/PhabricatorRepositoryCallsignTransaction.php b/src/applications/repository/xaction/PhabricatorRepositoryCallsignTransaction.php index ab13c6a571..418acf476e 100644 --- a/src/applications/repository/xaction/PhabricatorRepositoryCallsignTransaction.php +++ b/src/applications/repository/xaction/PhabricatorRepositoryCallsignTransaction.php @@ -25,12 +25,12 @@ final class PhabricatorRepositoryCallsignTransaction $old = $this->getOldValue(); $new = $this->getNewValue(); - if (!strlen($old)) { + if ($old === null) { return pht( '%s set the callsign for this repository to %s.', $this->renderAuthor(), $this->renderNewValue()); - } else if (!strlen($new)) { + } else if ($new === null) { return pht( '%s removed the callsign (%s) for this repository.', $this->renderAuthor(), From 54ee51d7abd0c527a2e2d5d071f38eff71c367ea Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 12 Jun 2023 21:48:20 +0200 Subject: [PATCH 15/82] Work around exception in Herald transcript of old tasks: Call to a member function getAppliedTransactionPHIDs() on bool Summary: In some cases, older Herald transcripts which got garbage collected display an exception. For unknown reasons, calling `getObjectTranscript()` on the HeraldTranscript object `$xscript` can return a bool with the value `false`. Afterwards, calling `getAppliedTransactionPHIDs()` on that bool throws an exception. Thus as a workaround, return an empty array instead in this case, like the code already does when $xscript->getObjectTranscript()->getAppliedTransactionPHIDs() === null. Note that it remains unclear whether/when the bool may have the value `true` hence this situation is not covered by this code change (the code would still throw an exception in this situation). Closes T15343 Test Plan: 1. Change system time to one year back (or optionally, use `./phorge/bin/garbage set-policy --collector herald.transcripts --days 1`, drop steps 9 and 10, and wait a day before performing step 11) 2. As an admin, go to http://phorge.localhost/herald/create/ 3. Select "Maniphest Tasks" 4. On http://phorge.localhost/herald/create/?adapter=HeraldManiphestTaskAdapter , select "Global Rule" 5. Under "Conditions", select `any of` and set the three conditions `Description | contains | Internet Archive`, `Description | contains | archive.org`, `Description | contains | Wayback Machine`. 6. Under "Action", select `Add projects | someProject` 7. Select "Save Rule" 8. Trigger the rule by creating a new task. 9. Change system time back to today 10. On the shell, run `./phorge/bin/phd restart` 11. Visit created task and select "View Herald Transcript" 12. Transcript page displays "Old Transcript - Details of this transcript have been garbage collected." and shows no exception anymore Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15343 Differential Revision: https://we.phorge.it/D25246 --- .../herald/controller/HeraldTranscriptController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/herald/controller/HeraldTranscriptController.php b/src/applications/herald/controller/HeraldTranscriptController.php index dfc0dfc0b1..4bc569538f 100644 --- a/src/applications/herald/controller/HeraldTranscriptController.php +++ b/src/applications/herald/controller/HeraldTranscriptController.php @@ -717,8 +717,8 @@ final class HeraldTranscriptController extends HeraldController { ->setName(pht('Field Values')) ->setIcon('fa-file-text-o'); - $xaction_phids = $this->getTranscriptTransactionPHIDs($xscript); - $has_xactions = (bool)$xaction_phids; + $has_xactions = $xscript->getObjectTranscript() + && $this->getTranscriptTransactionPHIDs($xscript); $nav->newLink('xactions') ->setName(pht('Transactions')) From 7bbd657c19c49f8d1ff1bd6382ff5f1df2d7bdcd Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 12 Jun 2023 21:50:14 +0200 Subject: [PATCH 16/82] Fix PHP 8.1 "strlen(null)" exception when Diffusion repository has no tags Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=diffusionEmptyRepoPatternSearch, ref.master=97e163187418, ref.diffusionEmptyRepoPatternSearch=97e163187418), phorge(head=master, ref.master=108cbcd09bd3) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/diffusion/controller/DiffusionTagListController.php:28] ``` Closes T15461 Test Plan: After applying this line, get the expected `CommandException: Command failed with error #128!` due to ` fatal: detected dubious ownership in repository at '/var/repo/1'` (plus a `RuntimeException: file_exists(): Passing null to parameter #1 ($filename) of type string is deprecated` as a bonus), instead of the previous RuntimeException about `strlen()`. Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15461 Differential Revision: https://we.phorge.it/D25285 --- .../diffusion/controller/DiffusionTagListController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/diffusion/controller/DiffusionTagListController.php b/src/applications/diffusion/controller/DiffusionTagListController.php index 15b8dc93ae..ffc6a1a9ef 100644 --- a/src/applications/diffusion/controller/DiffusionTagListController.php +++ b/src/applications/diffusion/controller/DiffusionTagListController.php @@ -25,7 +25,7 @@ final class DiffusionTagListController extends DiffusionController { 'offset' => $pager->getOffset(), ); - if (strlen($drequest->getSymbolicCommit())) { + if (phutil_nonempty_string($drequest->getSymbolicCommit())) { $is_commit = true; $params['commit'] = $drequest->getSymbolicCommit(); } else { From 1c098c273d06ea3cf8215245ea109f41c59593d9 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Tue, 13 Jun 2023 07:30:53 +0200 Subject: [PATCH 17/82] Fix PHP 8.1 "strlen(null)" exception calling Conduit's user.whoami Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=master, ref.master=7bbd657c19c4) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/conduit/controller/PhabricatorConduitAPIController.php:686] ``` Closes T15469 Test Plan: After applying this change, `/api/user.whoami` correctly renders the "Method Call Result" Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15469 Differential Revision: https://we.phorge.it/D25292 --- .../conduit/controller/PhabricatorConduitAPIController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/conduit/controller/PhabricatorConduitAPIController.php b/src/applications/conduit/controller/PhabricatorConduitAPIController.php index 3ae402cf56..208ee81d53 100644 --- a/src/applications/conduit/controller/PhabricatorConduitAPIController.php +++ b/src/applications/conduit/controller/PhabricatorConduitAPIController.php @@ -683,7 +683,7 @@ final class PhabricatorConduitAPIController // Otherwise, look for a single parameter called 'params' which has the // entire param dictionary JSON encoded. $params_json = $request->getStr('params'); - if (strlen($params_json)) { + if (phutil_nonempty_string($params_json)) { $params = null; try { $params = phutil_json_decode($params_json); From 7fe622e5d36619a2932c0945fa6d10fe33d5fe2a Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Thu, 15 Jun 2023 11:49:18 +0200 Subject: [PATCH 18/82] Auto-subscription: little less verbose Summary: When the user "Mrs. Kitten" adds or remove "Mrs. Kitten" as Subscriber, usually these messages were generated: Mrs. Kitten added a subscriber: Mrs. Kitten. Mrs. Kitten removed a subscriber: Mrs. Kitten. This was a bit like the Spiderman meme self-pointing Spiderman. After this change, these beautiful messages are generated instead: Mrs. Kitten subscribed. Mrs. Kitten unsubscribed. | Before | After | | {F286215} | {F286216} | Closes T15347 Test Plan: - subscribe on something - unsubscribe from something - all other cases remain as-is Reviewers: O1 Blessed Committers, bfs, speck Reviewed By: O1 Blessed Committers, bfs, speck Subscribers: bfs, speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15347 Differential Revision: https://we.phorge.it/D25191 --- .../storage/PhabricatorApplicationTransaction.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index 56079efaf2..c03cefeed0 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -1033,12 +1033,22 @@ abstract class PhabricatorApplicationTransaction count($rem), $this->renderSubscriberList($rem, 'rem')); } else if ($add) { + if ($this->isSelfSubscription()) { + return pht( + '%s subscribed.', + $this->renderHandleLink($author_phid)); + } return pht( '%s added %d subscriber(s): %s.', $this->renderHandleLink($author_phid), count($add), $this->renderSubscriberList($add, 'add')); } else if ($rem) { + if ($this->isSelfSubscription()) { + return pht( + '%s unsubscribed.', + $this->renderHandleLink($author_phid)); + } return pht( '%s removed %d subscriber(s): %s.', $this->renderHandleLink($author_phid), From 8e6bb9b6903c41751277776a0c4b2a3fa628eedb Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Sun, 28 May 2023 16:51:11 +0200 Subject: [PATCH 19/82] Correct Phorge icon on Auth Provider page Summary: Add Phorge icon to auth/login PNG files. Closes T15403 Test Plan: Go to `/auth/config/new/` in browser and look at icons. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15403 Differential Revision: https://we.phorge.it/D25255 --- resources/celerity/map.php | 10 +++++----- resources/sprite/login_1x/Phorge.png | Bin 0 -> 664 bytes resources/sprite/login_2x/Phorge.png | Bin 0 -> 996 bytes resources/sprite/manifest/login.json | 5 +++++ webroot/rsrc/css/sprite-login.css | 12 ++++++++---- webroot/rsrc/image/sprite-login-X2.png | Bin 37744 -> 31127 bytes webroot/rsrc/image/sprite-login.png | Bin 16010 -> 13862 bytes 7 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 resources/sprite/login_1x/Phorge.png create mode 100644 resources/sprite/login_2x/Phorge.png diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 84d27ab4aa..aa1d6b8014 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '76ed87e3', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => '0cb47e9d', + 'core.pkg.css' => '051ab1ff', 'core.pkg.js' => '2eeda9e0', 'dark-console.pkg.js' => '187792c2', 'differential.pkg.css' => '525f9a1d', @@ -184,7 +184,7 @@ return array( 'rsrc/css/phui/workboards/phui-workboard.css' => '74fc9d98', 'rsrc/css/phui/workboards/phui-workcard.css' => '62056e3b', 'rsrc/css/phui/workboards/phui-workpanel.css' => 'bc06f022', - 'rsrc/css/sprite-login.css' => '35d1510c', + 'rsrc/css/sprite-login.css' => '8d16d643', 'rsrc/css/sprite-tokens.css' => 'f1896dc5', 'rsrc/css/syntax/syntax-default.css' => '055fc231', 'rsrc/externals/d3/d3.min.js' => '9d068042', @@ -342,8 +342,8 @@ return array( 'rsrc/image/phrequent_active.png' => 'de66dc50', 'rsrc/image/phrequent_inactive.png' => '79c61baf', 'rsrc/image/resize.png' => '9cc83373', - 'rsrc/image/sprite-login-X2.png' => '269800ec', - 'rsrc/image/sprite-login.png' => 'a843f146', + 'rsrc/image/sprite-login-X2.png' => '2f61c306', + 'rsrc/image/sprite-login.png' => '7031ab39', 'rsrc/image/sprite-tokens-X2.png' => '21621dd9', 'rsrc/image/sprite-tokens.png' => 'bede2580', 'rsrc/image/texture/card-gradient.png' => 'e6892cb4', @@ -906,7 +906,7 @@ return array( 'project-triggers-css' => 'cd9c8bb9', 'project-view-css' => '2f7caa20', 'setup-issue-css' => '5eed85b2', - 'sprite-login-css' => '35d1510c', + 'sprite-login-css' => '8d16d643', 'sprite-tokens-css' => 'f1896dc5', 'syntax-default-css' => '055fc231', 'syntax-highlighting-css' => '548567f6', diff --git a/resources/sprite/login_1x/Phorge.png b/resources/sprite/login_1x/Phorge.png new file mode 100644 index 0000000000000000000000000000000000000000..20b6c1b2159b631b8f6a45ffdc58a4f069c98bf4 GIT binary patch literal 664 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

KT^Ih^!~ZeSeNteK5;0Z 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 beL{e0aNa4agq*=oS_a5SDoWIf83+Fl%?f@e literal 37744 zcma%ib8uvB^ky`%I?2Sg?M&RUZCexDGchN&ZQIVoHYc{N?XR}>ul?25cGd0M)!lXP zd(L~#d7gtCt|%{o1dj_31_p*CB?(jp0|O`h?|_8{eWTaC-3&UxIY??bgMlFr{&#>U z(IMl3ff0jA0fkjPGS9O-eJ~C_Mz*KV;z)bLO_rPhmi#Rv30XJdV4c5ceCJH zrd*X1IvTL~J2l}vIW=L?y?p1}8;pR(sN3qW+y6g&h_vTb)j;|0FLoo>HwSIfWg}2i z;^Z(zVBmG|)Za*Rh4S({0O1_@=Of$Y7WO(16JPmAoLg6xv`fi)+tn4Afx2y8pNXf* zQzPri3GTDJrz85RP<3ahn)S8$GBEq3G#Dweb6|qZ*x1O3-{1p%i1B6uP!*AEVV1xv z0=NR~A`d5L`8-Es!zEeZBk}3g9ngM>;T{4qY|%36+-UKkjMb8ZIFk~h!fxa0Vw8PoCfP*nwD+xvi%0SjR}Z zQ7^TKKTXipdJ%f@4JlBy+3jQE=7c!|chScvDC<)Fzaxu);l@d27K+T9rIXVig=l(X z%t<;)zvJ;WgM`Cu8>YxdCiU2*m>1iJF8Tr77I0kFr&mS;rpC2-JVxtru5jj0r_TKl zMpBP}m2I3zuE6=))D zAXMtI+siY5yWohV25=OKi!IWJj+yC|rm|Ar9Q>0E((FJ^lG`P26IV;8B-3Hg<^Q5$ z1Qa3kAu#38^qaCH+2Uxa_BWy0h@M|Huws2Z)K}xV&QoKntf3EC<;ts#vXI_GdeHTM8*|js0G(7!KjJ6{-ta^kW68g=aMPGO3j#t0X8*E9{p)`{7=e|wsE)#F=*_-g?1++l;pqFY%UmjFOn)m5|xUpDkQ+P{@dQG-^UD*1gSi z!NOKc2uPW~K)&MvtnZt9`38g&LRDH9b^}`vkWMUDBYmqK%bNl28xo_aXrIEBV@VRS zdojBhvPm)mSx5;n%?qqJ1^fW z_WsHevMxU(CzZ3}0xQze(rWue6!h!qQA(2}7ZI%ue0}vIjT=Q2jbilYP7wCJ;SlSM zq(%u7vBE88P~njrr5THGt-z*cndlh}>+P4IZ8v@g`(`rE{w)?`CWaVx>fC zb>eGEm@19xW^$346u+YHaPrGHCyY#3CyG*~R6#|IerGaL8hV`Vm1RLlfiUg;C z(7^DlSt3OkU3hw#CKm7KpdR)~dPmytb$ijBRyRO^0d%IU%i2xw`+YtM{wg0=S)Fgs zJ{+3a!4i3XqsJtB(d5L$L}un9148V`ye&`ch^TrCJ!=DN*`|)SsIRYYHOa7FNi(?! z%~er8d++Z#_DCQ0am~_yTS6>vii7Ww;MlOkMX7U!%R+^UJ5GrrVv~pvrCf>|A=kG{ zMe}P9*P7PLj5`LsJ+Dy=XAGlNu!4}GDMPtL(h-3Y%8t?ueepqKf&W~d4umjk!RBGR z$(!V;q?zELEn#?uqzaWzMzmD(lfRX$9o$&z3R+BqX>tE=4vXrOy>x zn48N_U1moYTZKv9qa#AEYIMXZicv_=MdSG$JYrBpz~&?`3Qh9p#QfumkhC$~#AhN^evg-ID#2u z#+peIX@kwM>Jgt0`Ee!H1Sj)A(S@irbc%umPv219@o%Au@>abVtrB|Ug>p$fU#sa;`!ue`+~WZO_aI)e1;* z#if`|1o)PY6}(*ksmV!NG!&WNJW3CdEFFRgj;KuR1gR@s+HC z#M5vG(ulhNHt?FNm{oiGqI}H8beC)k(7yQf-jhe1rec**cv$sd&Z4xIw3^O+r(x3{ z@$CNRri~i9wipyT*^ZlU`}T(z-iI*ShB9;I(nu<^y)-^IZvlPQu!u$^50x+$MsB{e zrUqu7PJNf&GK_@`8&Q7xG&$)XNg>v+X_9ZAO44jy=40e|Mc`w#HFRO-zMV@$F~n$f zr|txR@GxXmgninH-H|pQxomD|?qM&LkN{d?>$fPHDs*NcwE}V-I6uIRu{iNj#2<8T zF}jW$&3R6^v^np{yf1>l?{qFG=I1Ih%*=Y1YU~Q^xW%}u=+uKzd}AX~!}6F3ERaM7 zmZDk704xb8mXnb+m-ag~V}g8tcT(RF=Vzd) zE|Wl=D@W+g%kK+`+*dt7JeUXs9mbU+<=;?5`M*f-VLAGoCDHH|40GdPrvP~fT3u&5 zd89nA=&#mMcjyfD7!X{n9}DD2wk(a-c&nx*Kn)|l0@-%HjJ0w7xoY` zE}BUS??!)ddG0nvpI5^T%QCA!w5Apet`uSZQ6{yHebbA_KmPpHo4HPR%G5^04tao7 z@WUt(Q@jzDdj9h_nzuC!Hm-3hT3m!j-!*AF3L;ZlgMImN`Q1vpi*_jpv8Cx80JT?m z7Wfgq{#@PS(zx3LZZuR?;RPgsP(8B8Ut8H@chbE~>x#`V#U(Xr^yyqB&?@DgAkSCk zaX@DdT%urNKB~(Sf#EM!nod#q*Y|lrFs7L4t&h(H__s}rOmmX@ISG>{_}apy)p-kv zKY_liK&GG-Z@OTWpwChC-Dql$2b&wI_v*<6+bSnH!OP=8YYaWTveO8NP|#^Kb59Kj zH-l0)Zhv55SHYd@EDa-4g_`wkXn!OJE22eza4)j$(igirDt3Ke*`VzBL-B`?3suL- z30s6<;2Wj&ovo8LXR_mJGJri`^fRwt(xlPYfpbCOs(PX!uLfmQiE6T$q5mQ(dO0Ho`1H#xtF$Ct|=GUb}SOBXz6yc|x zSV}fju42yWKd*$8{`S87%N5NbTEG^V0Q7B=vMA~aRq-3Md4}5>5-@W*#MP!;npiJE zbo$H^5`^Nn;ZkbQ#iz}7AQvHGSMvj%+%Z#Rc@b1Ttl`?!)4mfB6nv~};|;oOVZ(9T zi8RmhmXk|-TUl|5OU}g$@%%VvM$8Pt%AiDR5~Da^lYsh?rrIqI>4!o|7aWmbI~Oc_ZPbhub>ii2#DXYL`?8FmTI@Jsnq z>+_9hjj6akOwz^NN0n7U_2eRBsxt>MXgi`5rkS_cOjCtdoYq5xSa5c9KXERLlPqXb zCxx8Lu8^TN>aU&L(JaO*r2JnFSRX}Q))ShY8?n1X_Jf-aJP+RRW`!b1plP{=ynU)D zMMQ>@y@rGM8{c8lDy>UqbXih%QiEMbv`0T%?8;Wd(lpfpcr;^E0dJqF-ldN?hw4|iS!5X~{7XciNdSA}NM=j!qeZCAgCy+h8} z#%yWttyO~H-(m6`**LkcO*rl<_5JM zVe+F#;rv(M@os`8cI;A%d{}h;+%6YDAW<8jzVB*1i;%q+Aw1%tL7>J-2k{0v9r zScOhjiH||bX4#NOFB9ZF@~|EZ;mzJH?utSS;D&yo+_UJ$`xr^-nPypbX~MhJvV@*NiwtlSU#!TJp9Fr8K;XLOzSLa!Qb8{$T%Og-3~L)Z^c;qtRK_c zOv>p5Go`y-Zfas!$W><4P2=fWITVBB`P^iMdKeG4AdZU%Kb&|NIT|UXa2CBTy2J8k zXNh9|5HpGkzYg<^ik6?3oR#?8pM1K|Y!1zIEudZR22+pt6IXC>Yp)Mg;U{Pck zFP(0W0oz+eeChfPi@38C6?RNkh*gQfmXW4D#}(DZsngavy+HB==_*&y4_I$3iCL&d2^9j!crhZL9WrRYu@^-peDUv(+e^#=bN}JqMA&Fa9 zU&$AXn)Nk%W=m~oaYd}0l*wVhVn`GGH>W^lISxwFBAPH}J(abv!-Y1N0>6HOdBx8h zI zsl#I>!5gY(kQtAU!(aQ|&fb&}c6jSZlnmUAiB_^C2XOFQ(X%8{Nf}!*39L7d7~w|+ ze`^d;Wqq=6lgzx!nZrmgj$TT9Oe=1*0woBLIacYME0{!kV|2mAX^xUK_&Un4`aaG- zKb{S`Ae~?$EP30H2e3K7q#3cfa!;;;EHcv?Gc^4T2MvF`@=>>eQ?wb&eRG^bQZ_f# ztPa}%G4N*hUwi&(y4szOA|C7S38k+i;bp|(=keL5=uJ_Ia(=Dah8yY1miMiIj8(T|WTmE|g=sO;cJl;eh_axOzs+>u6Lb4ik}WhwnXH@5R=YKP0S-(?gQrZuiO8 zfUFF~ZO!uB85cFYx=?Y9F!L!qwnP&hQ5;-S?P^#y9eabx!RvivOKSE(Fbdp|#o~J9 zNm>ibZirwE+Nh!vUK`;EK$}3)>d5tAE2L zFk7MWt35+UWb>`PCw!;*PI#$gNu?zS&xx-&&2K-})6;|nllME_2ohkkF1^EiW6f<< z2j>jSsd3U=`4*fbpKZOH4*p@$xe&K~DqE|v4Yn!)X|+koGHijSAxSx2L1El~M=A3# zDWX*KyFH`<#u!6U7mpe1*`K+nv#3f-wq7Wtgki;x*N97?Ey7E;G4OYJMglhW8G8T* zDoX}UCdZb06~prKQMxsE=}1GW>M<7$Jj|4Mr+m-m_>jJ#5M#^RS875l-aTUC_gVcG zJ`5Y3`o&UY0PYREp_P_{Vn50xTNlT`@-imefWDRGor1}4*xQyDRykuy*fxNd?Qe9} zZ@1ja+~)YMrUxpbAS4vV_sJ08Xm(-(lJp1|y+`JAu$>br!>RF?UW|{jxfkiRmSkQq zP(-5u>2s8kk~DHK$qbN$wOz&`*o*0N;$Tb>k|bHOB4F6V55-OD6Yo6O#i|&t@SaK` zFf5(a0|u^{M-A2{OnVwUu+oJXDD^ke$b;T>a$+BQe9r_e zUwQbUkY=@;WJ1w_`x*hzX!#>Tv^^H5zF>LbhvDNwBA}xGM-s;oAVbuby5y~-)ciHW0zhcG&HpDHKrY`V)X@&`Jv{&NI9QuY4As6wn5Xl$W_G4LCW z2snZBD9t9sg=&VDe3Fm+8+L(?3nNLhZ2ji zv@Wk?em2ZO?K(F(#epSV8V#XiXq6k<8HJbJyfCmg+Jn^s7vYo%oN<1*L`*LgX`*=) z#*k93!jmAResoZF8X&ye=Xb3H0J??}>(;^XRVc`T`Gpn=c{r2@eazd;Gw zuQ}h`H$^Y#e2aif$N>vNwnQl*>{P53-S3>%KQu&m6E3i#XeJ@2#LC2Uk`ozdv31nL zMqhfhARqx=G)3=@_7lhamR{?||JqbZY{fmaXg+EBZFEwS7r#f*5a=@(-=9~>luXL4 zhild*qte=nCKbZfgAyMU+3D0SZXsvDlH6|3QpxYIqU*43s7!J)mRK{@kZ|Xh-*=NF zGlMsj9j>U+)J{~3D_se%fn#U1!;|CO@Cc1VR)BaS!R8JdjBI znxJ5eVj8Ikdygi@7y%~ItSk*v{+*Uu5w2bvGt_7pQlFfUr7s087FSoeIA)EktUCZK@0~bdpHt$%xp}IJ7o{ z(E~9y4O@ow{bWDWm8 zY!|pL@;m%c4Mussq3nrCuMNDLtrqWvo%W6R1CCBHIH)-z>^q#O4=pPc7fkaS8o)L0 ziVT-3a!a0P6inEtJp9>+)gYNPKq8OsbXY_AN-z;^*;{G1?da8r2FGyXo+Zb9m|36N zGIcpd5=b#?-qB^g=8=qppea-6N10v&tDp{&zkdeg45m26-cEMT@$qH|xVFCXFcFGd zx`|liP~rp8YaZs<2&st5NU}CpnmQtf@nVa8L- z07XB6X;6C)q+YGOd$Io3F4Z_aA2wnGlgnx*9?nRc2<=!=h~&1?qSyiO8OpJF1$G)}zgeSj8V(Z{aRV|{zB~Piy4ZL5 zqne13*|1MQ>zau%kDpnd$^gEK$BE91bi5K1kvvQC)Ww-S*$ZnT?7uwiwqKiY@@J>1M_LYo5hU>BJj$D3u`<7&Is3GErFq zkH}E$k6@_TOemVyd3Y;ie4P7|o>fYVls2BYn^lQ8uS406V)opJIyj@0+DzTB%}mLs zRgP2qBnvbzxp=pueuxT#`VRHa7UfR?1`p|dEKYUSqe4l>V7X}zqFQBUSmg$&m}OCQ z-Y&?HssW>$+^(ii&`e|jk6cn%kiT8YBo9%?6f-Gw=r2{YU)N=-WHlBa{O`2|HfDca zF8oa&Z<^ljhXiTdI5RG%Nzi0qe&At)z*Zl%Js`bhX5&$l$}|7~P1cCWB5t{dvrA0U zc%xe!t#F05@M}UOYBDUQe&a9S?{w1bsJ;z6SMF~y zkpQ)Kc!I}q=3$d&N0CXXCmv8E5#A7*_>yUc3zEa|!KUXAie1NWg@-&BYa5fijZ#Fco5Nxhr z_+`-+vgtn@sz{yxsw~3qu@;dQYn!469v2rH`*ZaZ8zmlx1;vFK4FSxyusvMX4iDE* ze(>5g1hLtZX9fZj%>tH8pvdDaJBrEoiTO#1owN?)OL!^J1C>u%?(ALgGAw0JD6Maz zHa7y=2-71vc#`%QRi&%cX%PO|0FEGhb-1^**zPX6heb~f3a2(imFArbz{K#G&>RN? zS79!k&=e&9-bZQ)V8R0Ht$6OLa$Yhtp#xQit(wG#NQHK96 zw$msB_n3SpJP@W~BF!F$P}t(FSbVhD`cdKcuPc|7O^(Z#T-rritQR(8yULf;Xx!Ue zH@VH!NNi2MlSLnOUplA^-V5PhX3&`?)n+>l!Ku(h*10NDp?qF4m`Y0_iIN|BE5tlh zE#yiB&hkUrgKtMu57e_<`bZu4yy2(Q>4gX~aQhpw>nJ5u33ooZIIjG(hKQ<9#Up-b zp>204{#+t|jGKo$pIzV(BzPc2r1@fOmj^?T1#NVndAx9_1Sv1d1Ppe@w>B2%tqZB1 z3)Z78UOMiZDQj|8J#t;kH9y;wE@U)u<}cE?reBUAW%sz!=Gn7A;t?@n>oiLOt3{}V zrThn34|#1xAG@wHKaDoGq5C-l4|+j;!eow=7Ak_&2plE7=&EgPf4de>5O?SZYzgpY z(KwalIE3gK*7c%}CQm%RjG*Z!joCv}kgnScM@uBGiVGuSW^EpCD~#hu&LBij>HS%} zsxIRr3c%;GVjpu33@d>>U;y4hWKT+aE=Syck~#PJHt^2*eLU+>k-dJ)MN!Yk(hfP9 zG;U1D08I}3?^%E#I*egKh{&AtM*3)myy+EICiC+NFaS>2KOOiaGE%LWr*g)_-(SIL zTcW;*^>*X&R#|1xO>m&{6Z?c&aSdd3eYZPC1Km7h0gq1|EFyrFYoA}mb3l@o0JBE)Aap8il*O|)G!352i ze{q(lW<)uY16c_rVwLoZ9x+EzUtvSK85uf)ZIAqqT>t(u_rnBfyjqofB3fd0M1BJH4x&Gf1y*%nekC!@9w))aIp93KNQ8NU%oIe(Qm*y|g<> zvfnHBX6NhzYw^YE9{BYO!^oiV-N<#sWE7LoJPVUz_M+zo6XNc?@3F^qY!)d$h^N!F1~2LMm#61>K%o~jFzOUfgTrs#TAWF#Mw z>{C*8*t@3~nRWk!oUE_ER5^&N-M(+N7wauVcLym3k83UV2Ku6+qF^(irsiq8>zTUm zC`qU--~08z@^=i3POk+eiLRIPhUv@aJ`}%Pg$&Lrw)np#P)#-6to4rvSk)VEbIvA3 z-N;`p@MqVS?fPwOBc(?GK+xL>=WMA=F@IvLB!od2!Jb%JF?HPh>~3?bY5 zvMp(EIJzQ>*Y(s-M)Ea#GjI&X&t2i8#24?Dj|RcFC0;QjVW$0R;HojE#RA@5~k7+eKUZF>fm{k$mdM z-Nc6QZ|JPA3ASn7o}ZiTdn&Vsvl2vIkD1O>o;#cF+j^hxchee0`ID-o${HD6ckV_0 zHNL(Nk|HGa67LS;hC3`R2hkbWDcIeIf?u~Goc5j8)AQrSc&@JcKL`_HJ$~f8j194xLhVVmNzhA zp+23qeV-N!8){6i7dNP?%e?B}jlclE2mBo0ieR$XUjHVao`c31IyV&rK6N)U?D1>N z(jz&s^Pqh~pSHHnE>Fl<;o+Cv`)AgJ;tD9u!4)9IXe_HCxa|)j+NuHF(UN?CXnYPw zRtNs*6e}%+3H>(XOTU-m&ZBH^ug-@h9d`!(&gb%}bN7u_$5OALXCdiBM>oj;RC zNppC~IwADd`D2V$uM{XFZYQp-af8ic{m*45#2gs~8afuA<3`zVaO}G?pPAj0DYN}n zXXkf1^>?eAe?wUAZrhPqOrK>Vdw;!e|5DX-@5jryxw?IU<=N>_g*5-XEHg7DMiTCX zA?PG4(8#&?yD%wmvhcz&{eDO3yWYGtb`)L>hWqZZdD2wV6`$pMTQ*tlrWX*`>%By^ zcyWn^U`j|WiT9sI>i!%`jfVI2DjNdZhvzW=Q$^tI?d=;Dz2?jbxv2?g;%d*y$>~>3 z&*y6*$UbPQ=t4MyeZQ(&VQWyrs*5ak?kEl}#;DJA+AfyPwq{!FuNX)VaeV}cybh-P zTy4~!ARZAOZ1+pU#Zqk&8RRtH=rks(Bqi1jBnnkXaW_Ni#mFS&@H?G`Hstk=x@bV& zz{Vx`dR&lz{zT+7N|NE^?Cj3Y&VIkuY^Nhk`^x(-jI8xKA#y=_}W;c{4O|MM%t&@k|QVB-3@ z@$6=2XZN)`5SsJ)U*z}zy&+pE2>ymf^77v44V+$BSm;E9g<3+vWj{{kyXw3n3IQ;= zBqk?s)fo>(s1=AuYp+hJShJlj*PKOG!z8k5jH4F;%F0dvukUyIy~U<$ql~Y@VvFY^ z|J)<;!U>m@1&y%`U|Q+Av^^dcH5zJK|3$!%#z_{09_;)^sm2%ZdA|L6>-m}woa`O5 zsctjxa~vVixSis=ii!b}F2WGF%q*RspA!(q9#yQZt?>q2ZgyA%5A2Gbo}Jy^40ik9L>m0KKCP%hCg8NyELl+} z$99ojL}jl@xqh5>_U%G=g^&^hE_c0n6^)IRvpimmgN6u}^`|E)AMQupky;tkgJgi1 zw6wH-?V#vplFqwSrPERca=f1#YlpEvZbx}{miIFHg9CjYi&e+W43OBU4DIykEU8~r|B!I?U*`#E}jFZddoN%ltlbY_2$ zP{e;5(>3D8FE;v+Abad;F!yV@Lb7v>ekyNM$Tc%xl(Msnp%%Vp?j{ViJ9g`@CCG9_ zrs*9?wOMNk>Fdp9k3GN(bU~ZFWKU7RQLoZYVskrR$w=p`w$g5Z-us4t$xfOK-0;5Y za_tRC9wy%w$Y`|+wsnsh~!43I{M*Y&Y^ zEo@C&z)Z8t>!CG^&z&<~-1dC4qs8HJqmAd})E^WqRzarEV0-zTV&Iq7W4%}|fA`NU zi`y2*YcNv`C2ZvPr63;Axk``4$rWNjH=_j2w_Vh1QIv`cx7(+$xI?27Tq?+% zrfZy4SJAiEJ`O?%1WbC%8}RimZ}%$!-`9IdjW5vs$12Lpt!L4>{6F8v=NA1*+jBgp zOtuL5-Eh3H=S`8ut}Lc|J{{$*3!XAm4YFq3FR^VGU?7c)AbFlg_P$bi9A-}MV}F>n z;%lx*r#ZzVC^*JJ%}D`af~+5(dcL~0K{{Q|e>!VFt9~H zgou3aXKxhv9~J^!qWi*ywm&m&DfJywSV>XC!QhM7@AV80FTLIsVi$kBO`8`<1n_@p z`k;HkiXiR3Uw6K2hUB=pTSV~%k3!$-(9AfnJ_<0li#Hn%k8$|#c`bYL<-O4CK_rCbSUGQV2 zrk7};bxJX71BiE(dSCQdJj25qRQgREVYYX=&HC`cKc_qLi} zvwB;EFW3(cssbKFV|!wrzEH3JM;9Qz(jnlza`Hw8Cw!C&u`zl|9tY|nfiSxsgznWv zHxu4ewCdHV>t^Us?&mABm0e_PYz<4yQFd7z$)Gq_m6n#a`1W{V!+N$imBpvipi}tm zMX%H9a`|C)qPq=2BDwtYne&8iO#?bDyr-2<*DeuH7&Dta&1gkx(iNz2p(kgm- zn}rt?_{eXdyTDtSd5M?jo_TG9mSHQsR#{oO#_#>;GOQTi-zV7ZA@LD<)!k(<1L-+CDn+wAK z_U?l;_;YyTCszlXyf za<$gwp>O4|8H!NkXVC2NgBt4K&ggtI%}0VB*hHKXOdjjP+3#XdT@qO*x!+%0@;;k>J0+fB(Lh z?e}_Oe!*GR-!Lt3=6jH&!Dw41Yqa|r=Odu|U^dM^{dt#|h4Oj%Z|1A}_=@L#hE_CI zGm~cL^LGZ(+pDM>^?%$7U zlUV-8hoc;Sfvf?`AU%a-Z#+()IXau`KXn|SbZ(azf43f4~7-|V71Wtz*n{6o9t(&Nr+!PD#hd1a-;qQPxOIKwyeVXe%} zY!L@Z*nc1dspL#YfNvX?BiBb@JOSDmh{`YWIc?v@`1J0G;yV1Shp%Z_19Z`rmY5Cx z(07>?BSOLFcDMl9ZhF>pyYJg$Haewj>fQAKih=h<({i!P=3^+4pT~0$96I68@F1`l z-qX^j*T;)>nj0Q(jV|t5^MiR6o6oz6q52l+BmlAZij{qkO*xh+q5J!KsBC)u8v3Yh zBJo9}Rf|9($Ns*~WA*b}%|n+rWcsv)x!1yvFo~PRgoCGZy@xsfcK@$?`81|wG>}uJ zx|ytl5(N}#cOnC<#*{F46`ru_%cp(>rc8djwMJ^dH;6#PtF0~#E)Y?E2PKOz5S0c! zelzxdcNxJTUhtChc)of!0Y{a2-FMNly=C3pUwoah{XYEm`F2H=kdfj2xKO52^B=y) z1%X9GMp~fYanfI$4g0?g4jlP$biD6|C@g)q{zUA22|dBt#^Gjg*Z=`eyMr;s#4j2_ z`}#{j(Njpk*ZR|;jlJJX$+jS1tF8+xJ%l>=aF+RT$#l8<_T9C&=|muwd}k_iJ9Y;R zzzo{`9uRd;Qdd)Z0GpT7*VX-DH=fMESKrVOc{H8l|FPBO?R~!0)v;{w^}6g0jf~Ij zH=WI2!PK@N&vDiB_1O##34N|zYbYEUiSpm}i3)(2ETIIEugjH&zUM&@h%X_3J@3UP zj9sQ=Wa#jNZunBhy_{V8G-RQ$`j8?xjrehO=ToJ_#T;~L5#4?=lkQB(Q?_iF)V%Kv zktXT;=X`!zH=g4;NMdbXf2mj4=8iGTDX!;w^a2f;#F$ZmygfVg(2C~U*(d0Em4rbH ze_4Acp?p2GS&%XHxHUwCBH=wM<_P#QuGgE%fCBTmFNg(A*Hl*vnD_nqCWtTS_r47x zUj|4Yn^%5Mk%L|w92`8qVNmq9wBJNSk@Y|`9ShAdXFA)jOG}`fNN~pMZwyK2#a+Ww zSNAIhLj|5Ob}6FZY6%Aatlem>TUicR+fnpK?rWO=Mw88Omp|r&r)B&N5z)f;H1yd%5pK@_~;zbM;BmF@9wO)L`gRQ=Jk!PrjxZa zFR#yg!*Rq;;5hfUzD%>P-g1I=?#wW#8p2x8+Ug;tbJ~d27c0O`nA0`UmP*a>!hJ8n15`MPFPL%{$SMI`9=LQ|5d?6vKi zRiB9?zS)h>b_|nPY;;~dcK5`aKafo^i!pYEqIDLy!&iAkX&)>4^rS2H+lnU?v$u2# zdz9;2bsaA_NXPOQpk&ki;pHf&r+@1Sba^C@Q@(w9KCW6A_}xu%VZ9%6^~{3(Y&%Ha zsIRZ5Oi1Mjo|oriDBFJf&t=#~2))mfK)~Zy!e2Xfgg^sGWG%4>`g#&;Ui!#Y*EqLC zY7@kjFnzkzf4p7X?Dk)qP>os+jTV!3Ty}rMWYuI6X#@li~VXQh_ z($s&3QvFS~Vf?5)47T89PxiI16tLU-W)ZX;%PlO>^GS7e?)}zOsT#dHv;881Nr`vtBCb ziCs9q@$$mg&f>a>IO`zrzx~V{SrfzRqsYf(c0Qaq9YE$g&xRrN*s1*dc;mvUeZK6t zq9jOt0)-j&7w@ODW%~>MrwwO)Kfh1C28-#-_(j=ziKus-$1;oe@s$=VwgDXKoRl>z zjhJek4s)xE(-iriGTwPi&4(PeAD~I@j}aQ-;?ZqQ>oZ1|XabD7E>PnsOw(x~ ziI76^okqp+%NKU~eka7-wC(&tAaq!|SZz46(9m;TWJ+exSu!hg%3684)cI)E^B>a5 z$>h}J%;eV<;QvqeQw}dK`+w`L`ePr@pZ7KuRGAEZc-$#4Ufvv_qYRa4daGB@G%LKB zJ!T($Z8jXX`G1&>CsE}1IK4iZ?gby6Z*ttt=D02Lv~e?EHzCN%QdReSdR5idGTVQ= zJ{07D>bUWsh@8I-Qo-Fg-p|%u`@aiccR63WK6}wzTiX>HHF9L)QJN0JI2QDtXH_k3 zA2+f78}`L~ARJcS_WeHnX?0buF_rYn+c+^{X$wdVvAr_lZ+U@_(LLfjzn0T>d!hw4 zj%IJZt+StaCy`SaE{sX6ULyn@sB(nniSKD~SzO9kFs!?OLk2{df|1;Y zgOSMhj?|d3f_G0!_G9Ei8VQvITsed!#trF9hda=d5X;(o2KYs3R^KNgD{dvfVgCb3MNt)A3I7h6g5Xr*&<+qn20C^{g4~+yn_)-@+?0NL>63-0cqs> zx?z{dA@Vm3#qZ7XC);A#)KSl|1-UKE$fdw7gVeSf`5g@R5cm$MK=fEcu$v3vHxA1#J-zU`8Fg0 z0abpU$`te`j-AbM;(7p4ZLyCI9mj9Di+gDO;8MD0zYuwzB#r|qCd1==SJk z2*IIqk3&;@-ffjlB-ek%f4w=`f5mA`dVhX2U0PUTZ_BqIv*pznKIC(-)!GhQ+n*hrk0_1U}GTLe}~gTm@E zM%H@)_b`UuY$2-qBLXWG4nOM`OM5M9|K3w58I_njEVMv*KsIdB%AD+msH6f02W&_I ziQ+y4F8sVVbnY&U7ub|p7-A^6&VT|6ZYwfT8+-0<(<|Fb=9shG;BCrMtl!t>w70VZ zWjNIeC-*5lasO63^w!(4Kd1oq6}i;_oSHr-G#qR6XY9CJ18@;+k#)$?z5AihvOImv z(BQJWy`lM|_ov?)Kt6$21b#s**A@GSi)78GTUrDxhDKua30=VM)oos)3X{nS7`>vI z!}7iy3xz2z@Z0;z+NX9gL9qY%Esu$mdT-W(lRu+`;_^#9%Lg%r3MlB}g(gB~-1Hq< zq)_eqm+831_D}(UA|6O+Jt&jBuyEW;j-ga+nz$QGFKB9^Sc8{1?QL>@lJf4lIA7zl zMoqjR_JfxaP({Oq&1;5U%+MQNPC2%W;koXS(|yBpTE zP7Fka1^ZCk*LEZECQ6l7Qx`GOPo$t&ZO(zNzvej?6v=vM5uAYp?+k(kM3h?{I?l|~ z0eo8>mxWX)Y{b!&;o_11?U2Ys+vxtS+rHT>Ag22LkaKa$^O@W;?RhtF(GlX)vh1(y zOlcrkD6*Cc!F`AB4<>6T!IvVufmet2tOPTBkPm07)WZf6X)6i8&ZQvkWfiHq^D|A!|145`dLgw8970$g?I@r*4$(FE7^v z7hRt(w^Zl>p=<2d_OQx(-3BW9Nc0NAe6BQBBj3Qx45NnJ(an{2nEuZ!0MLumaA!yY zk{6(wj0H{mBVd8H^!_wX8bd7=%Cvwg!fr53LUbiY97UF+YHrP97&Uk$Cg;609n&07 zq$bGdLZno*fa;IE=fB=q;jn&cLD zx^OKhgx}Ty)e_g1A}LTHr)7{Fl*BjmyO0ZU=V$*AgxD%}bsG87nZN(B+nYsoVO@d8 z$SoaWm#Gnj6iyY<;oHRN{i30=3v(}$+zZBxMG(`K6EJg2-9pc8=t$ z+St~{wt0g4`#)9B`&)I-tCLEqGU(~<`OfrbtjK;PuHjqmm!b%|E$?hRq=pojCy!7f z>=qM2hm$C2!$)8?wQKX!H|OsPQy9GGtOv}JP}FY~amBX?37Z|K2-lXp{r*uLp~yQ= zpNl6qi?}k8af^!a$P5(Cl>EGfZGu+^o6obghy*mV*$;c$|MXiEYhx(VrS3izC6F>M zUl=mkafm`5%~br=1)}s4`M${zWV%GLX99Ct#W_!*5?FGhy#Ry-6NOD%44Pk6JD)#2 zyc#l+m00B})Ba- z6r1>WHKXtSYISfG|I>XeeuZ8j-i$J&)ZhH-L2M^qEmrP;tYdR@Z3*tDh_ig5zY&}u zgxrl;mdigm_%ZyhVn*VP5s@FFcM?!e!tUx#QPjPEEyg~$O?)iA`Z3!bcvjRQd6p-G z8fSTMDv{Bc7IJpx_t>{3nDYw9Sx#h8?>CY2g;zbBuE-`4u(CS2bVbZA$O zt>v;wNWiFTE&JT?3R=t*^=!^y%8ck}&W1klnRG;5$>w)PdkC)jO?$f!tEnyfJ{)I@ z-&Si>yt{04J6NHjPr{M}TF@{W_Rr8I0D-Ql>0K^^rr@k_3&<)U@ixSI$YnP4*uHg! zmOE2<`}0A10UP!SNNr$oA2zG&k60glgxCw;?o1=2*O9jHh1sF02NcXDC}EC3r&hvg z(RGr-B~@M91PkC&)wlZ8zF)dLAZ30>;x=JH87TxO7IsTBfq+)<>_HAi{-q-D8*L!a z$GoIe3E!*Q~mL4CMfj42FBN9?cH?EJX^z;ooE-f)Qa?@5ga4{&T;9Y2R z>Vi1k{B1_7ucl2+xa(T)O-oBlx<{7ou?}=?lo7I?$NH@%kB=$f?Lz z$Ir92NEPfGs%WOS|p%>MW2=m`0#VLAs z{Nu>h?X(+`w$FUyV)rI=&A}C>_*XtlU6iu6w880B#cMGOcYYT!4K}dxeFwxRyMfw_ zUbZ)EN?W2ZS^{^P`9Ag*J(O8MJ182~zwIANOoIg&7G}?&F5SxDXye&MbfnGlA!g|e(Og#L@gTN6d?$CBnBek3JenF{2wg(2q%=Pb&{6-* zNH5q`85a{Rhcn~t*Yj0ReXaPmRdSGeR79M6XgQov`|&(R-wLb+QiotgFc2Ag_Ewxj zndMXcNRauUDkay~N3!!k2dj&bWUfA_i z6DWc3;kUkn3v%YgBN(^PkjU=)CFn^ zDq<=u$I%L)mqxF{Ko#Z|8h=r9(`lfCr`WN11=qKS!cY{3U^F(QYfoiWwOS(sBxp)jfj%!w?G_BF zqScl`XGR+Ko3ZYm-~DZnL1+Bdt2(`=KYM_dZ^b(*3yOUf>?RSr`q^lr-F{pG-{W_S z#G=$6>g8z54uoQLYoTSm8xbg@)J5d9$iyjgbSs>>Z7S3Y7h{uJ=AZg(8o1F?{{thL&pmVNF7QDvN zdnEo%QHoIID6XF%*|?U^JMd z7=2keL^?yFZHLb#pgoYZ;)=SbCFMcazp#UI2g?R09#~|bdwe?z(=Mz`-~>5W+7isI z!&AV?X<}QTnX$|^4Ju-x39wPwi;pe+MuW>lrWVAu*CvtO(T??hXK^JKKo9-tC3xI! zE}t8E`Xe2l)!G9Xa)V{N$ik)^Gln76&hgj4~^8M(IJ zC(pVk!j=VP6Ufa%i>>6!e015+)l}FSN78UFO}o?Zm0UjI*K$ZwN+eoUwLd(q7@0cu zpo6#v51Jy4?v~KVAEBSCgmZIb)c8FnfgNVwbs+GPcn4H->nml=JgU#ksXh=HGBRdq z*A(U2``Q1bKV`Qj&~)E3(=+jk-18K~cNz!--(TEur!kpZ9GXmE7&PUs5n}V~BSm&3 zA+50Ba7PH3`@sU1N@E)n_UE6OU~ z5^Sm3(eu@%uN9QXS(Pv7A1j##M#jZuR@wZL;jqBPRM5DP2OWl$HHr$-qLTnOVuDa_ zRV*gf{Ng%Vi_~Gew4L(V(ba+Ljxne9wJRQS39PVv<%9W8I_^`c6KdjyS8}9PBeK)E z%H`2|y!YFa&9OMu#~1ii2vUslpaOVxWOEpRCxrUTDx~k~k)oMIstDrd;g};Sniw`o zC6Krw){as+3~nV1$`FoK(+58&+vlLgOGIG)dxt(Ep$8E`2u4+Jy4}X*jY+O6&TVHy zq67EN_mH=sN7Y~!iq#|vv_3A9l&FBrm7}Rmlto0WW@R|WuR-ohA7>Py z-CV6Ij`J$v$BgB~^g`^Z;>#*?T~;rA%^!Rf^UF!Q`FyTe5rj7*7*kWx%i87`Ix-}E zy+QGUKl}5ysj*4ho@slf>AQPhE%U4Wm_u$P_32v03F5uj+Ry4)!!C(f#JAjg5n!9D-?X7Bko}KmY{$GYkRlk*AsXgM6 z|BTsQWSnSku9?6gVbET`QQ`_|@r6eR`-;`u&-LyTao%-8G!bu^>U7j~G-CVO_!)>c z%VSzma*YG&s;7KjsLgnaLo;!5R8o}Ag}p+0^RNVC!}RbeG+!j^WV0m#OV?kW@w?iJ zUai%1Ew>^Dw#XFV7Xn5QKQXN5XOffUJ#ZxMCp>WBJ^f&!$zR?>Hv?WxL|?mZ&ffR) zEumC)^ygj7Eyi&nvb{{dsPS+M@PCG?HJ3Hk+o@Rpxjc&r?Ch;eO;c;Ja`3h^&c&Gf z&?l<^@8oY~M14H*cbwMsc2;GkTud4jQz|bxEFs7QzQ*CrH!?H3F3ST%q9tl3-Vi)D%6Q2w zGa@5eL`5DavLK?BnnMdAXKEv2xY2vWnYO@O=ewHv-t*%rEjHKP?X8sHrUe~)iVE#jLW{`EMm{X8pYwXCk((Wdya zy|uwEd`=nIhre(OUjq4%r%FUf7D99E(qd2%Q(_!MKo#mDdE&dMMv-+ED~DYh!Ut~* zzL9WT(+0f;d0m|J)1+vg$(ME*Ef_AiFQ_rUwq@BbRe#3iL5%W0)6ry3Zq%XLS31S9 z*rGu%H=r=u;qb{s$$t}D=8#~4;L}yK1B1LKtU}g}<{$v4Y@t6sQ{V8SgFjf#NxVHh z&!-DeYN`~(&2__=!5lg@#vWwt4X~cX?!a47945)f4PugJdLq*hVV=;S?{3DQd%Bar ztlb@c^UTb<5xA}j--ZYwC}EBih!PfWW)P{NtX-r(Zbwa|zc$huYSoXjJSeuiP*upI z*LVuVAZDj<<=v6aJa!~wpKNP zPPeK-KxGbyr=jPO6rrJD2~4wCqQViUFi4WdWzjP})MW~7-*g{pUDu~(yD)_aep%@8 z@eFo%w1{*5Ikn8jG!j+kc{*y0L+B3eZ@bfGcVx0X)KKGjGBwtK72H?hd9qlV@S(5X zi%t}oedP-**xiepe!FG8)~}(=!r-(^z(X=$fq)pnQk_GrS1gEc3WAKai^`}n>9IpU z`fS9FQ0wAY*2nsV*AWqf5=HZs*drVE=-*$6f3$ekg>8VZ^^LD>X z3YLubIc4Ze358a63=X-olP@=z5{GOes8TB~h+!^I^*}ldbc_>7A0bFi@=7CUvp}&; zhkm}Tsic;mnQ6pd?^eht80mSIO5Yld>!MwOKjNFrzZKW#>`mTpH zV&%^9%JAg=Jv+3BN(ny76ADEH>t2W+2O*)rmWe~iVSk@*o^Zl(x3M-V^eM>tduFP0 zo{Ddqz;)!?T*HK`*Sd|2LE&mgAS*>b$HLd7LKwb3#Xe7(o3z)610KhIvk=+6(FaI$ zJRb12hgHUtox;jIPcReZdQ|m+wyd^h0Vhy60_XLl)M$bm#c-!0pxF(4Ev=h;h2)W$ zDCyeWq249y3>z?}pG?M{XQ&#|eVcII5K;2bI?VZ+eRvFYg3L25Uf_hzC}oQX3qj0? zjjr$~kIm!4bZK(fsg$EsuH_WpnBXs<62%1P18K~<4#(c5?`+R9h%As2d-Y}cf_H`; zf6jcxrX00CjByJjC!Z~05!fJEhGt=u-#y_xV^HR}m+GiaZf;0$VZiB?x1jf5$mgrr zY(9_3IFVF)vw9F(peH?*B0Y5=Z4Tngz}Qu=y`^CDvnnrHR%jqBLt$tZ~A|n>3Uc#ljLo@6SSpOwWi-{5ey8w#iJb6J@iPho$HBXRq!!>)A>o%*Ewo zt#)0Hs#ic{MQc9}i#z9w>-q(S748W-qZ7%nsw z^4H-@HwBp*neH4TRQrx(d0jp-(x}2bHQO?buE_8R8l1YTfK>+ZYY2;2j-!roCDNZv z91)M;jB>AcCOdU-4RFFKm{YGLAqy1_mH3wp$Ef%A-;NdCW#U`jEF~i>PWO|&g|zm1 z($3ZREL4k{sTOLAe<^ZHiEc77+%#SIk`#`$Byc4NoZt^LtZ;@$RWFy}@wP14)K0{g zBDWhEsPY-c-!9TyLIY(XDS6Yj(VRfsK@&(HBYxXI^Hw2xbV+T(A)17W*wfU%CMpK$ zf;&51OJJ~3x7v08w23s7`YBiV+z2}R4ZUilmisNarRos_l|Xq{Iik!#*!00PZl9j`P_T z1zifI0uQbZnn`Mx*~5U(5@2bxaJTy@N=7zo9;2-m(Op|eeeMz)8c7j0G{;^WiitA& zv}j@g6YL3JP)B@zM(b4{d>njCu^rGMND&kHto$nNw8swtb50QTC&|h%XiIVYJ)ctf z47}yUk6khjtOc%t9YF%~P?o6t5U0anx4~=^HV(pB@MpTQ_f#huMJyH!Cah=*ckPo@ z`%f;);)Tu6>28A$@k#uOF9k4cvb`2+Bj4t@h_6-{C@`5t8*`4i3Ox9D9CToZbvC0& zM5IU2tLB--DZXkf`1u!+_u0Zi`S;eY>pGxX!@XhWt%YL5ic?LMV`V5FXwxfk~|>Z6KRU!nkEp^D3f7xcrO!KPz_zJ0;UWu95)FGN6hC4IM+LG_UiQ$PxzkqVN#I9)@gOuq*tV z;cB~j;<`u`RN?5-6xvj{%jzvi11Zx~dg5Nh8)7E*rugW4+{wjrTD)L4m@n8{;ZcN( ztQkB7Vn%tnobil1__$)>ax|!I3-Ma`pRPk*Gr9!A+c+d8_5Q5I21i?eAhOUszWw^R zJ(y*~-aBeqCqwG=Gx+k4KKu(9-4e^&Dx>S&w=Gt7 zBjb+ge-;RZQ1`zr>s;?*^vz+b;apA1c(h`H$QZ0ft&d(z`%YaQDj^N=d1ZK63fWBR3d@@h5HpKckE!4h0|SG125g$(b%Or- z=Qv43*#F`)xSY#Wv-};M5c_U8r$)vfVN5&E&|9#EFynCqf7!lP^GjVV+yI7zU~l+v z67%Q?!Am&D8{_yL8PpuhSdpndr{@xk2W*6%c9!$KYqbu}VRW@uFW5xWGmLwCk~D4FcAKHIC!wr}t14;Qdz z2uDcfTTbSTn(|W-aa!oaUm>-&2-u)Z$6gEx931<|qXh=Y2DA@*k=q~l4S1e#E@27G z*$sy8RR)3e{zJ^|fL!@`wG-mQo0W@zC0+Ecs><9IR|vbMZHT`dr0XiH@*@g@2=ZT= zoK6*#A%mW}&7$;cQWW55v0XTq7kD0EuaT}Px8+zbzjS;09O6IvKdpqZ=>&e6)jCUx z;F@mjsW067c=TzMQzC8nqS6${YVK1dgXyoHA5gkA!8rZzV^*s4&?5mm+Bp?1HW6bZ zC+l{z1e*EneItUT_FP6#MCHe*yRqlW;b8B1y=1ZGMGr`q8$&oPy>{s0r-G@qtMU zJ0M6pf@w*uG!eFz0o$Pmc#+ z0rAs)r%h@f24^F`taTs9*br915G-eCK^+!6y^$%w0MR$Te5ZyF3*-3?6 zt_i=EoJ{-c$+Y1}d8H>L7JtUI8K!KWFf<*OZ*?5ieJ++8kr-SDT63$xZ%M>ijsmh} zSi@`+EI^EfHiVWP$4R{uzD&&S|EsIcL%bs4L*595H+ln~uY3vBO=tp|?`_$0jgS1( zb52tD+?lyciOoXE^+pBQvd;Qh{Z@F~u;TD}V@8r%RfoKp#BG0P< znpaV%U#!b<@#oS)t;Z3pE6LtT2$lt6XO*#4R%A9pToydO@mvIR&9euIAkf?DgP6Q; zGPN`wXQ+o_RMOmgktQOfPk!@fRja7$JEu$uc4DWYF6qj92&b_}x{|@pm!x33%Tr!| z-DU=av~@uVz>0{{!kxLV-B$}#1v@9pWwoGHILOr@?=SXOY*}+jc7_h+Al|#@MsE_p zJ~2&vrr`^F-q>FL%r_xNS0JH_rB!x-pxW0HN<~Y{M<-XsX_AuDW41_N3^6i7N^Ws) z)H|bQ)*`UJ^}y;qu2LnmL7qHitmiFV6UJnAKJ<83Se?QfA$AjXBFLk5B4;-h|NpxH zHIUwZQD!F?!1_}(hAmlcrVIzHJ?@nlnC+Dyzcj8Qr?EiWetQ|<53Wo%pNyv{m>NP8 zziC0K(3hYQ5CLo{VxPfH$P%c{09;RsYk!PulkIoeZ3^97zQjl@5O~Q`g>+6oH1o$t zO_ck4gm*(wX81YosFdZ{mC~30f5!cFQI?!>7SsS_?wmC_Z{Af<+IpU3~u5K zfrf|iYh*2RmP*;CaXRMP6r$;F@d(Zc7_aO^O z6)P);eVLG$^Ub#BcXYe4Igz?ju`Bi)qAH5P6Z1ed76y&)G6k8N8S&xq`HnoO?1!i0 z`+porT9EOGr-Sav0$`>D`;Lgh@adh1OD4uYQ{|4!96XL9u9Q&)o>|e)0ol1daY<9T`?A<#aKWB~Gs(9ALS|LlB}qN!pl> zA32^{F*9bnhB;g?Cap!di{K^l#7x6k`cRmF+W!c8a)gN|4Z}BXhrMg?rZWG`OuOMq z7W?q$b-LsZ>PmZBXfio+2Kz*PrebL(?%iwThVsY+`a;+Hw7X~&tFH$fq*MX@GMxCC z;E03$J9hXDsc)fH(Tl=bVzie}zD9&2C#L?LaYDu#@~$NA9MW+*ASf*8<~WVs)^l^( zbfV48J4Gl5HS4LEDF+iw61@jzibl*(yC-(OtgJlJGm9Pzg}5qzbv;(0fm|}K3OuSSg-;5*eu}QrV-0D`yyZ*#;dCs=?#PpXGB6$Tja0@hRp21#( z30T$RkI_c&Og7dqm9k&?#t1btW)@+cR|$06HY}X_{MSqtso~1EEMa>*@|hDiw?{np zKLi9+f!^^Qs=M=*BnC(t=NbZ@j`t^^SKf~=#rALjT^v8rh687atG(dbb~a`xv8PQ! zV`HIIr(`9bZ{p29UQ;T%3%{jct=OulkWWyqgB)Nv&d&IjL0GjSCOT{_~*KYwg7Wz~9a76re4t$8bKG5o?jTa0nSA%m4wk%c~!zZqJ}!O*v0(SPEg>e5QN3mf$5m|um~&dnmk(saV#?otm-7diL<2jIRW z(@+PUY*_iM)FPJ`h#mUok3O30@qIf4yFEEHUXb-( zdUX0V{+RlhHV!iz z(jA7rPE;TI4@L}BZ0z55`J7Cb!fClTq%8I_1B%<)-Oiy(lZWm*X(KM!&xj=~-n9MQ z*J-(PBEsX8ja4vAaX0_+k=5|I-hNXKeuo&U z6f?OvY2YGxSo%2K6_@)pWK%i>8@SDq(R7X{GzRAgu6)eyhtOtR+8)Cbc{YB9xai8HPO77`kF?QAG(& z#L>M6T|kN!gBm;qibWteoRRO+gT3dw@X{HjwONRWmjoOuv?%>g8@2P~SE_p-TZ2cp z9jT4#YbXo+)N7GZ$9b-)%2N0ieD5d+W~8}n5a#wgQzIRP`^Agrs8HV#Xbr6zT?4HR zN}6`IQ`6X6qaSil%B14oj!mr?s8kc&;*UxrpMb#+m*F=ozk=ib`YXR$=O`?s6qwE7 zFG^PIOLd>`TUueUnr{jP`8e4x{qOON%Uh(2m#M3*mQm7jTQ#&c@rKOTb`jyke8cX~ z*F-lIUFMG}0_hbpBH`&x)EIO{Y6@si=zeQ!=*-4LRRZDGWGJd4`+4eN&j@~D%?_s- zBA@y5Lj>FRJlP(4M6bv2-rjZ5HHf&p|@QkUivttn3V zC19u!eu24jA0@Hwm&)y_6gLSmQ>>AuA#9zmY>P-VktteGV*7}a_;QtU&BR^YMmvHf zzIAOk#%fb_&csUDs3*yAgm9991HDztCU>Q7EV8Uz;c^JKFePyo+!v&5eb(-+PgdZE z9_W`p&QLH}ugYg&|Bm&3Ud_`-*0WsYZlvY9kd$n{NpnxVXkbfhl+U`!qA^8&1Y6f$ z%6uh=d~rqO&T}tv$1zr1{Rr`zS1L4{JdNlzXvCG+BX zT8qMYU?hj4s(JJjzfnx~(U=mX@l&Wu)>yI%D#Il1v7e{GCoRv_p+Tq-MlTHSE5>Ik zpf0v>72W9mC5Cv*2=t2WG8gYz*_ji1OA&*cv^e`$u#+ z3v>3lqAImzl3tWBTSh6%d*WZAn}pI$n!-NZq1Z&JGE4odWPyU^T0K@P&GjZ({YF7# zJoJjkai2GjVW#KSPAQ3uWMDph9$i_x=q|285tFd0(~}oB!%rXcplCeBv|K|3$W$mh zDFl*YoS?N!A`D@NVv@{RckeHuBC>63Kczf^H<|useIO0HT9QI(&Mzrjl5;e?95vxh%R1!@fE-HcG&eg?zprGtxv3 z0QG&35@Xc#^T$9Xru5PymVGf<*pRlixwmqoc+s27ku7pX2P4Nmmtq!>ZTtfr6hTS# z;)2EnuG*gH+|V)lRBxk}OVIOqaQVUFF)w7rnkA*nnX1f}q3BB8eS&tF(n*OV-`CKF z`0kbpoz|~896R$-k35)&@TLQGd^`>)Z;8?SpXpNOcSIMp8Ku=K!OS_k%0Ju zBFGRL9IF>_9|9>&5OblYU*>Znkm(0X{;XPgze?c0FTj3YLLS3OWge6hR-c6qSXt=DLU|@ zJuYR3;M)tm&0M$EbgSFLsA}n9rLqS|NFMU-cjAfRuvVw$yjD>4ujt8MEUBFXPE^yw za|ue!hPQsNH230}@_$u9_R}UqZ4xf_LNfb&QiAQB0E5F3Nj-UvM43Z{icAh}rf3`f z04_5W*C#Y#D$YD(Yt&WMN&3;7yhygNKEdpf9>ax*3biFMrPNdyIR%Q{c#dV?TYQlw z=f}h06vPKZy9}W9P^ayHZy+a~GqD4M=1!A+m_qSu_hmM8R&@fSP*4;;Q7-=>mjyyt&*CxgX3-|w^4}KRbU7MNJJr^cQQDx#N%8KI{ zid!|}+xx?a_-QOW(4i?CwF7=)OBsp=H&}D5^)PdgT@UbX{eEGpA(z-^5+>`hEZ9fm1^j%NhwIihiMbNwYaJ4ikO+&KxkhONr3j zde`A%{DoMq8BM&netr8rp$USo#EXQ{LmU%q6p0i;KKgLr$Kf1UL*cf^XyK`(V0%miY1pKrv08+$9DjYOi1mER$dszazBSC0G)tgQR(ZrG|)OvDseK?QVIQfrnb zKiHfFL=D~2`j5X`{Z7vbJ2`pfJ$zNpWQE*AF`3F$V`ZE(c5->DYkwa%HN5j7>pCt9zzTh+S?c- zMC-9$@Fk9AAI^3`s566a(FhIBo0+O!jJu7`)x1ju8@$wkt0j`5pY?f)+dtN1-wf)- z71HE>3X_q}3Vgtg5(H9I_sUbmkJS=#Ic`3lr{jKE!Ms$1HhcG9ZS+bgWtb1xPrUH} z-nwg268NMCGy*-~XdDBYJ&~XI&coDrGX@rNk@%{_$F@&Lf(+-$&(hrZS6plArPdOp z8ptcMxhbZ{8OiItkJVbWnxcY>=8TnKTAO=shlx5_vzudS_B{19l8{?l4(*8yND#LM zCTu7Au~?eYzJwnIl~PpcY>66e4aJ6i?d|;RO0$R&25xd*T$7v6{_;d9Aj40?e`IIT z_%~Hh(wEiW8HX?0)ebv^3v2Q!_0qtRhUbxBj6NnX}(sAv=eQs_}pO=?c zZa9JTvnJEA`=y8h%#)%PDshl*++|u&>kTOC{c!#Kcu&sE$WX=#GwkwSd^(x8Gy@uN z2yn*?GD?VnxA6Y7to}!c;?{vn^t(TvWhWpYkXl?=00`t&lh>ek9wL<2hqIPjfF1F+ zSJkrlI`-So-iVt))cnWT4L}`y2mlJVNp%`5CYwkSBL4oBfI%hcY|P6u?gKDLI0jw^ zsTu|+0K?!#=@Hk+_s2_xMrHLXP*Y3|43?T57a=fc@6!P7(SI2rO7QD1PZgv(z!$Xr z7G!>J7j@!P$A2Dv(<2M1#E9O8hdPYD?DJ?Oq77X&j9j{~UkgRn40pX<=xAURwL!(?HekCo!KZ?YcvY%VD}@x8RT6zpy|NZ+PnP{8cbC;!w4I+ilLn+48h=$A-DN z`GSGZMU!xvppUzC=a4_!d==?!R>2X(tw`D~H5pNGuvlbs0TpeTE|vVqr+uj0NT67l zDs4W*X?cB30$E1e45v<7jEW){j49Jf3!yf6r$B(W#R9={15P_|!i_6G-H2l#fC3b* z*LC1B=|6ARnGHAo`}Z%}dcI`C2N=2@tZ5ekpw?Qe8zAYSUH}uZWzq0s_51JltN-ec z8$5IN%!~Ad_cKd{Xx0&OG)*w*gLMz$=xY1J|+mI9&3_yN$g|xDDT- z)0<{E(L9OLmcGraZa=<|_ggH9X>lDEq(Wm<*Fvd0c>#pLfOmi%`8LObgn)?ndm@e1 z?6K%uvbXtUn?|K3@22No+^}Y~{)>IWa3S!^y({6DQ6>Kw%p*RXNH5;}|Jov6sscvs zATbt&qTi6t%GPVf2cIg5UZ8Tj@$kP zjC8I^@{3&HH(-Pu`t?yAV4SFpe>*i%hqfyLB!Z0u;g4tL;uL*=kEZk=QgVx!$H_RM zs%(8_WyMHi@$~QCzuuB6b4Gw=@dFU601m$^pRJD4(y13W8Vleah8W{oJequW0l(b( z@RV7PLHK|*B3x(d^jLHdEATHr1OvPe6^7SWC&H?Uz;lh6XjjF2(Eo+&Z->-A_871T z-aYIQPnVC~9*oCabzF5vy!i_QJPFU!$92ct%&e?`W@nRrzyM12yk9sP{i&&$cH$wT zjSika*$1q+8}uJ8#sB5txA45$(Fb3l>t+$7Du%Kig+ik@4&8U-4BV{R!H9H31N`2y z-dye}-DB?;PY~8M{l>Gecp0RBqp|m)AJEJ%6S~K*4>$2A>U+IGkgNX@?sA0O&(oZD z!f?9-0Ez;TA5~OVHVEJR#SEwhS|KAZkCcX^yO&4;V9$mDc%I^f8pu{ko?v!Ta=MAH z6C#JztABE^ezBKW_}1zxhsC7s@ff(pL~f1_rmZC~F;lQpQH{*u36&U5K&xJn z9Nes|vlp&>ng1MGK!=%*4(a{xugg7}Qt?FA!ru2~4dvx@F92GjikRC$e>~+SiY5oI zKH&3X2Spl`-dbV}z#Dl!fr%Bkbnjqx;~^5{;(X)7SYMD2m!Fg!pK z=gmU3%LR65M5vrGzyI7vu83N%Z(}e3xP}nnXPhP!580Mn^|IyEga#qn_1l zIFBKhs5&j0&&F0dEN&IPboeE$6;7rzJGk=GL7v!;JvxOXIGW$71M zXV?Nr90fW$I>VafO8eFN!IzWL+!8Jh4s&iUETSN^T8M$ zz~t=4nddb@C$k__nZafr5HP0+-u_cdZAa#>F1?xq-pOT~e@4B%`7+P`wS8qP^ce|} zrPMMY#w?%|>OXhZr7EkgQQX|jbp(t)uNWMbWS>RDY>iP*s((+w=ieyIEx=>6fU~$B z&rDKE$NLtvwRuI39}omQU++Ljs<0qIl0%8XWhs_&)6iG~_t`+wv3PZ4_gMgELE~Vp z$@VK?LlG+%kM3r&^75`AU!h^!ny$wNVt)5d4!ac=xvvOlnaJXe-b34RGm&uNNPo57 z7}IiezPXw}IWgASE{QE0Su(jIpOn=As~q7c{uv&Hz6!C^gRdOi-~_;8nFf%M%P(A+ z$O9}u1PTp>I(O%fF36*e_6JZ3Q(l*CM;1V-%~38u3uFTuiYM0l0LXst9RR+khbf2C zc1h{oUpS-0q-DKsRo>BFRaN!EzGdSvt`s0s0ocC|2a{tjAdK$+hda$dIjjiVy?em} z5SP0X6Y|SBf#QVN^mWIw4 zg(*HLY8!gFpr7+upyw)q6!A;i6q~3fq=?cImvDmHD zrUJmfmGiq7-AB4;F>&#bW`L}CLj1t$@UK-1z&z;{o>j@llvtl{^$2$q6zuBF#&-Y! z($60NIN}@yS1KstXsNTavqg{u^{VS>^J1g3GdU>@N~Mwu3yvYSg9VK-m}%D#{jfHM z8FhHZo$p%U`sGhp^^*mos~`(tH*0|&mBMHZLHrOGZay)Jt9545-d~fb>jU6I783kSz!QcJQ(3$ovUKZKm*FNq zQ&RSMfpGMh{qtup!2X=x0Jwdh4hH+*WaNX(6sprA?V}e`t@T-s7+yaDf7*=VN0Hu@ zTDAwCnF=uAr$M|yc%o}VpF`j7u@sd6+WlDF_wiqKOuxSZpGyCgT9fa<6^xpq;$lvK z$@+_nD>E)SI-2#r?mx%B5&+=3@r;tDwrP8=|L{CK0S~8(IEi zA!5S0kfBA_AwdF_?Z^GZZ(s=VdkaMt2&)iXsgv5nXvNwed8SZ%xj)}ua5E?xg$)un zxVbkjp1vcd2c#o}l|0I-p&MMLJ#BsbHVJdNI@{(CCT*{u zPm+u93+pjAg&K0rhR%O!I4f#6dc)$3Su9*YC9dEo& zk}vCfYv%R?**U|ChWGgH^yl5khZ$(jZD82?TWJR~&qaYzm)^sY5^OO_IdLj4z+UqZ z@Eg_$u@qu&*@m^BBXbDoF*gdS*);S%33zpV$oNW6|D|=q;r8y18wU%k73{L}ZYp89 zN>8h(g5G$u1IS9(!jTCrAXHr50Gs&up{S_17z7FH9KuDRp;2C0DYpdx39XBX;(u-{iaUXiRjJ3!hu zukVwDV7}qYUK7h{ozHjNa+{U90_81~4RqY!uN5U}U+dqma0QG$YLt4c_{?Fo{hS6F zl^j7wou@+;_aCEeoPHRf%Rf&fP0T9~{R3_}?SCvbHiT=IBLlwCC3E}NHB-5sUtPRk z#T`gDA7GisMwP$r<=^@YH4X9KLE z;vF^q!2j~hODiJ4QF!(^Zgp$)iP?Pn_U!?PBL`sC*4BjT8V7)9znRHWLNMjloUcHJ z-ivA%n^|8paY1*QlumSD6y5l{EKfzIt>Y+gJ>2_g#HAPC5^_^YErd|Jdso5>27CI@ zahmb&`(vV}v#IL?C-9bFnnAL6pFN56&CzR5uS4GubY6E-T(g;$c{_Ig&qOOh{)E%3 z*5xw-TjAyE-0nG_UVeTt$PARmdmlbmTEZmb<$W4#vW0g)X?S#`uijN{;r1F0IZguW zc{?vniV4>(d|Jvq+3`Hs%`ETZqJ5JGJmm6Sq3rH?(t5o0kBhs~F@K%2mVwvnEhK3? zeEfSdgKXw6Cw(SQhv?P@a@nMv&{fc~2a8%Pipa;)hAV zjF+PRxM>-OIdyFB*zTfgF+Tqhf5%2RJ?ds?r3Uq#pTJSeoE~g|?Kaba^db3|yNlH3 ztmnZt{$7$jU1!JB#R>C;=i!in8~?eQVvp;3DzK6X?L6*At`>1nvp$d&tQb-28XBfQ z8>X-87MpfV0;{UyPR?vJk8*Padi4aXhJ?-94qsnii4^8%II6yTYbz_)1^|0E#|VO) zFf5Z371VG~c93*T4aBkFnYYBWIld_kY$=F<>?X?_=HGxh|)jf*&)>$+q$5 zGsvSV3BvrNzo0}&r8PTFY)!UYY+w06oWwlM%nut~j=9izaNn&xJEC}#HL2FsVzO-|`A8Y{4ApfJ|?$B!Z|(8cTjlBEvismdf-u$><36dzYuhME}FO@OxJMYosz`p4^cYw`=br{KboK4zab^+#~ zr~AXT<$W?*%R$G->foXLkz;B~=u^7R&{26NRJaia39pudhNhH_gK5N~K?PVl<^WI3 ztnfk0&@iXncDedn#?n%aS1c?m&Kc<@8>Pp_Mz-CaJk!5=} zF_WGRteXmLBQ5{zdJB$w>^~{lyYUzoZ)w`!CSNii@hHYX%0>7HXt*Uv-*i~pa|_+= z-CS%k#K}iX1bDgwc1bbS`^G8`V^vn;-zB~1Qo$^9bF|&cRF<86R!Kk~e>ZWVjqsyR z*N{OO!!~%LFUIr!7ZVe82bNEQj)n!lMgVuBsM8%_ zok=$Wc&jZZ(E5;X&c@SQu61-AHta9K>ysS?Ud#Wf>&(BQ-v2nRt}VnZI~fv{ETd~3 zYu0Yr%FQ-|N=35EHI|0Rl5EMolYJfAH1;8~Gsc=_EEU6*WiZBAzi)rQcg}Iv%jV60<5b)Z#u%v=R)~K#*mNfv8XGKUiK`Qiuk0_J=E62FyV->-GTm z`S95Xjnku@*BlVF6wZw<3$sM<#uTBg8~(Bj*#(j!12E%h+RQ^5hrf$-sN<89s{h(_ zFS=V^6*y<-Iggc~O?x{P9hH^mk1Cq9j{2tiG;QdlYO2>d0$ps?=G68JqGIGQCL@cf zt-rk?-+hD`AH+tlWm~Gd_}srXtn8rmFYy4iu`727gMY@l$^2HJ#^clHe1GXo2K%4- zyFYB{-tQ^=P_nLSV5t?R}f`OdppoE}X<(>PEY6n{7P{*-}l+Q{C73o%*^U%g!_()^f$>`oan9s^^uJu*jrme^eoY&QGXTtZML}E_Y^V%s( zT)^=XU>7%0>qd>8ib7=`w;o+D8eKi^Qfeh9Pd*Mj-f%Z^8ZR}QJZBOrjNDpi4?aVx z1p;=Y0DwrE^E8?~Opvmfyk}@w&Z@cbr~nZ+9$abmC`xISKcXV^!2f2mAJA!yz!yQ! z5B*^)qVW(+@Zyt;C8K&hX460A$chjrY6b>ZGCHZ5ilMh*F+4Mtw%H*yrwy_@kfvKv zSfo5pp!L-57E`v6Drr|9G5VszR7P1EV-ZPw;cWiY2zu9T^Kg9Ax?y?v1_v6p+Y4h? zAk-@(r`N&5n_+f0Xy=eg_dF<&A~0g6g)0n0+6P;@$|MgVqqcDhf72~+?<>%aG#9|It<-tD2lzBqOP z0bU94u?u|?{}igFBqc4gWKXZpwH#&u%k*U@zy-)IeH2O^yr+jgfZ=_pL-lQ$Yqv!w zgCK9613WZwd$3VYmSzqXlT!Y9G!5rO)J2JG4EU|PtC-G(@{6}H$i<)d1PeY}G9hnl zWt_W*5ngv}{!yOM$*sxeED4EIqm~{ekQjGsu(aFOaoGol7K*|s&*RqR&4w77iSR^s z>roN!p0Br7ldax5_q$3Bl!Xn=1(P*Rn2I>w6Px;U>baJx`RbWitJ_x{&c}1KO|m3M zz#Ah?k|Y1S(XiH|id>}xlr65P^CxohB-B^hMM1BhkuMYGdRxr^+0)lIEn1LahCm1s zqyaf}p8@g3*|8)>B&6*pxypNeI<>7k*9Eygtx!@}*adT%C|3fCcI~WPAVJ!uarYpn z1)OPMb*DAICJh-d^KVt!G$n*X{9dLNI{qS&Z~_`(06Loaf{)S4%4&(&*c1P8Bk|mY z;XfGqL_ODDKJt( ziy1^;3C#;6nzJ5#snsarXqaR5f(tFAHK$Kp=4n?G`S(H7z%rHEx>G@~5Y)W8NVKKc z4d-Z;39&PQMIu-W!oG4qk;W2Uc1Q8=_}#zX_f8`l53z0^x38@R3}eTcFD|tt5(!&u zAgJV;vFN4Ji^o5vcL!n55CRlIPztG7${wQ0d!0?2o&W@9xP_S+H#qgiY~9-#Tr_@e zZ+mv1!Fw+NDGIt_P$R@OwW;@0C}9c(vCqAP{ll5K>8~2FFK#2Q?Pl9QFOB zYe}KT`14j2Uto7#E)*Yu2A)sAx%tq*yRO8;!?Qu()8BuntfYih8(VO}&PYI^P(MIg zWn{!ACMTO{fDGs_;GS!)>V(xru%Sy!(@bq_)Mcfm2UUSPLpb}*cJIZwX~PU<58IV_ZRTcMC?GnzmVBuP zWfMQZ`g~#SvluE3K?7Lu3h49kS06Lxx+(eNd#!^>d#N@( zJ)K|vna^OgX9COG(H7mkM&RgoJ5Hn;#( zHPMyyBNFO*jm_j=yV^^75*(^U#dR-MSGE-IS{q4OBb^LpKCx!EFAi&ab`4DA!k)YA z^wOspZ3Vhfny+&W0kv!bl0kU1Rs9K~;@Jn`%SloxS&kJ*?z=L8uq=+9_3WP>Ojn8x z1W@3>=mvdjRvL|l!5u9@`!)7Y*E0hR<7qA~ zQqpnj!Y+Eyx#?NepCc<9p4bMTgYFl-Lq1Id!kxaEJ<4B5_6n>uq2!-W`b%Es20w?-WNjx91dv0VDA*w2u zUd2tjX5XDc;NI76*j4i>rmv$ijgvhs7QO6`jnGF?mgT1X9oKcmGz=B5D@TtDRhPcp z;&ogHbj%aY6^*Cru~uI#FEg83t~{6Ime1$M$vAD*zN2 zD6($y^6&(tB`1@tAU+TXc~0XO=c!Nf&PGx^c}-0-w^dZ& znc#A>vT<_Z(i7Pfu)S%r(VxGZNAMxq*V_C|<28PrwaS$EXIhB!d)+sT(YUOa---h( zgci3xE%bIy+{RV52HVdjN;VNyiGD-0)lc-~bxInI`r76ouesK-9I;^LK0hSv>P)ONmT z0XDOwlQM&)R8nlnUDXq-l1D5pw!%mjS0^WbQeUE^+xu^JAT&QJuc{huvAg~CAb4C@ z{TurdrBpE~y|V|Y^?H(1XRO{|@CEjdCuri5(|P2tG^URX3*2<+lW$%fvsGu@oeE3y z-^Cf5nT>Z#OG`H)5Quq4H@Co@U%m0lZ}ztkbRV;`Hz!_Uu$#mti%zDjv@AmQu979A%&U)8$Q@>J|1pFaRvi&(G(eGtN|@M4q*w@J8r9Kp^}pD=T9x zb<~3%b*dz_ugB?D@A9(-tf+T0a$bEacuZh)wQS*kd#QvwS5<23T9|nf=OsUwyrSX> z7$#(Y(9f&)S{+Hh8*_y=3RKcBc!eVT;X{H<6eUFa>Ti%|SAG6$Hwe+GFc%zKqu6}S zvk|+j<>BGcq@Nc7QTN+LvUN1`vV=atz)x4)mD6lzl?($-WproBl04sI%Gp#7$K9%rg4AMC*D^; z0riMp^=gD>aQ`Cvh@H)gle>Qs+@|X;aOvq;B^4}_NO75&LZ2NE*1^J=f5Sg7N%U1z z%`FOYI~Q?mbmP)_x-fJ0b9{bN+3!BW*&%8^xkW_|D_}$>92FB|PN7nj`kw#QsgJb- zj+1C|O`A>@220Hye-(b?`t@D9KUqSH-Ib$=O~^p|+Nmq!+vfTI_m!`D%J5G_UdRI(z7jg{xu<6g`aGWm{|~Rf2}J+^ diff --git a/webroot/rsrc/image/sprite-login.png b/webroot/rsrc/image/sprite-login.png index 4a07583c0d96ba33a725ea1aab13adaf3f32aa1e..58a2dcf5ec0da01b47e9b8b6c13579cd83a77857 100644 GIT binary patch literal 13862 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 literal 16010 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 xqx$v@Fb(>2-dEjUpMQmY%KpDC8`u}=W{Wd4WR Date: Thu, 15 Jun 2023 12:10:23 +0200 Subject: [PATCH 20/82] Update Google icon on Auth Provider page Summary: Closes T15479 Test Plan: Go to `/auth/config/new/` in browser and look at icons. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15479 Differential Revision: https://we.phorge.it/D25297 --- resources/celerity/map.php | 10 +++++----- resources/sprite/login_1x/Google.png | Bin 899 -> 894 bytes resources/sprite/login_2x/Google.png | Bin 2272 -> 1446 bytes resources/sprite/manifest/login.json | 2 +- webroot/rsrc/image/sprite-login-X2.png | Bin 31127 -> 29663 bytes webroot/rsrc/image/sprite-login.png | Bin 13862 -> 13623 bytes 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index aa1d6b8014..a7b8a41aa3 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '76ed87e3', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => '051ab1ff', + 'core.pkg.css' => 'f3d35ae0', 'core.pkg.js' => '2eeda9e0', 'dark-console.pkg.js' => '187792c2', 'differential.pkg.css' => '525f9a1d', @@ -184,7 +184,7 @@ return array( 'rsrc/css/phui/workboards/phui-workboard.css' => '74fc9d98', 'rsrc/css/phui/workboards/phui-workcard.css' => '62056e3b', 'rsrc/css/phui/workboards/phui-workpanel.css' => 'bc06f022', - 'rsrc/css/sprite-login.css' => '8d16d643', + 'rsrc/css/sprite-login.css' => '0a370010', 'rsrc/css/sprite-tokens.css' => 'f1896dc5', 'rsrc/css/syntax/syntax-default.css' => '055fc231', 'rsrc/externals/d3/d3.min.js' => '9d068042', @@ -342,8 +342,8 @@ return array( 'rsrc/image/phrequent_active.png' => 'de66dc50', 'rsrc/image/phrequent_inactive.png' => '79c61baf', 'rsrc/image/resize.png' => '9cc83373', - 'rsrc/image/sprite-login-X2.png' => '2f61c306', - 'rsrc/image/sprite-login.png' => '7031ab39', + 'rsrc/image/sprite-login-X2.png' => 'c1458879', + 'rsrc/image/sprite-login.png' => 'f11dad90', 'rsrc/image/sprite-tokens-X2.png' => '21621dd9', 'rsrc/image/sprite-tokens.png' => 'bede2580', 'rsrc/image/texture/card-gradient.png' => 'e6892cb4', @@ -906,7 +906,7 @@ return array( 'project-triggers-css' => 'cd9c8bb9', 'project-view-css' => '2f7caa20', 'setup-issue-css' => '5eed85b2', - 'sprite-login-css' => '8d16d643', + 'sprite-login-css' => '0a370010', 'sprite-tokens-css' => 'f1896dc5', 'syntax-default-css' => '055fc231', 'syntax-highlighting-css' => '548567f6', diff --git a/resources/sprite/login_1x/Google.png b/resources/sprite/login_1x/Google.png index e0989b9c563d90b4f5c26c5ad2f6f7ebc020f269..4e476c811db4a87d9daa07ebf4c6119954eed92b 100644 GIT binary patch delta 871 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 diff --git a/resources/sprite/manifest/login.json b/resources/sprite/manifest/login.json index 8770cbe3b1..05f47947e7 100644 --- a/resources/sprite/manifest/login.json +++ b/resources/sprite/manifest/login.json @@ -39,7 +39,7 @@ "login-Google": { "name": "login-Google", "rule": ".login-Google", - "hash": "72e7b0e1005c92f059f4d5881592ee72" + "hash": "9a25ee35dfde4135db2e321e01b82c61" }, "login-HTTP": { "name": "login-HTTP", diff --git a/webroot/rsrc/image/sprite-login-X2.png b/webroot/rsrc/image/sprite-login-X2.png index 5a162a8538477459352a86c512ea8e4bd621d935..136a256c8baed89861cb97b705102b3e81cf59c1 100644 GIT binary patch literal 29663 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

KT^Ih^!~ZeSeNteK5;0Z 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 beL{e0aNa4agq*=oS_a5SDoWIf83+Fl%?f@e diff --git a/webroot/rsrc/image/sprite-login.png b/webroot/rsrc/image/sprite-login.png index 58a2dcf5ec0da01b47e9b8b6c13579cd83a77857..8810023ceafc6303a4479d35ff98234d7edc6050 100644 GIT binary patch literal 13623 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 From 478012cd463d06040ae93497c94fb5fadfc76308 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Thu, 15 Jun 2023 21:22:10 +0200 Subject: [PATCH 21/82] Add serious business string for defrocking a user (remove admin rights) Summary: Allow humans to understand what happened when `phabricator.serious-business` mode is enabled: The administrator role was removed from a user account. Closes T15480 Test Plan: Enable `phabricator.serious-business` mode. Enable and disable an account as admin. Check that account's feed and the general feed. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15480 Differential Revision: https://we.phorge.it/D25298 --- .../PhabricatorUserEmpowerTransaction.php | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/applications/people/xaction/PhabricatorUserEmpowerTransaction.php b/src/applications/people/xaction/PhabricatorUserEmpowerTransaction.php index d17418636f..3f3440ede0 100644 --- a/src/applications/people/xaction/PhabricatorUserEmpowerTransaction.php +++ b/src/applications/people/xaction/PhabricatorUserEmpowerTransaction.php @@ -56,9 +56,15 @@ final class PhabricatorUserEmpowerTransaction '%s empowered this user as an administrator.', $this->renderAuthor()); } else { - return pht( - '%s defrocked this user.', - $this->renderAuthor()); + if (PhabricatorEnv::getEnvConfig('phabricator.serious-business')) { + return pht( + '%s removed the administrator role from this user.', + $this->renderAuthor()); + } else { + return pht( + '%s defrocked this user.', + $this->renderAuthor()); + } } } @@ -70,10 +76,17 @@ final class PhabricatorUserEmpowerTransaction $this->renderAuthor(), $this->renderObject()); } else { - return pht( - '%s defrocked %s.', - $this->renderAuthor(), - $this->renderObject()); + if (PhabricatorEnv::getEnvConfig('phabricator.serious-business')) { + return pht( + '%s removed the administrator role from %s.', + $this->renderAuthor(), + $this->renderObject()); + } else { + return pht( + '%s defrocked %s.', + $this->renderAuthor(), + $this->renderObject()); + } } } From 327ac921c28b917dfc9215a7537c232f016ef07e Mon Sep 17 00:00:00 2001 From: Mukunda Modell Date: Mon, 19 Jun 2023 08:54:32 +0200 Subject: [PATCH 22/82] Conduit column.search: add status, sequence and isDefault to API results Summary: This seems like a fairly obvious oversight with the column.search API. Knowing: 1. isHidden - boolean to indicate Active vs Archived 2. isDefaultColumn - the one that Tasks get dropped in by default, usually called "Backlog" 3. sequence - numerical order on the Workboard are all necessary for a lot of things that very sensible real-world API clients need to do when working with columns. Partial cherry-pick from: https://phabricator.wikimedia.org/rPHABebfe30890b52784d222ec4ed36c05462b2a57f92 Closes T15484 Test Plan: Tested on phabricator.wikimedia.org over many months and used by real client apps. To do additional tests, visit this page: /conduit/method/project.column.search/ Check that the new fields are returned correctly and nothing explodes. Reviewers: #blessed_committers, O1 Blessed Committers, 0, avivey, valerio.bozzolan Reviewed By: #blessed_committers, O1 Blessed Committers, 0, valerio.bozzolan Subscribers: Cigaryno, 0, speck, tobiaswiese, valerio.bozzolan, Matthew Maniphest Tasks: T15081, T15484 Differential Revision: https://we.phorge.it/D25038 --- .../project/storage/PhabricatorProjectColumn.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/applications/project/storage/PhabricatorProjectColumn.php b/src/applications/project/storage/PhabricatorProjectColumn.php index 49d7f28a9f..e4359acd1b 100644 --- a/src/applications/project/storage/PhabricatorProjectColumn.php +++ b/src/applications/project/storage/PhabricatorProjectColumn.php @@ -271,6 +271,19 @@ final class PhabricatorProjectColumn pht( 'For columns that proxy another object (like a subproject or '. 'milestone), the PHID of the object they proxy.')), + id(new PhabricatorConduitSearchFieldSpecification()) + ->setKey('isHidden') + ->setType('bool') + ->setDescription(pht('True if this column is hidden.')), + id(new PhabricatorConduitSearchFieldSpecification()) + ->setKey('isDefaultColumn') + ->setType('bool') + ->setDescription(pht('True if this is the default column.')), + id(new PhabricatorConduitSearchFieldSpecification()) + ->setKey('sequence') + ->setType('int') + ->setDescription( + pht('The sequence in which this column appears on the workboard.')), ); } @@ -279,6 +292,9 @@ final class PhabricatorProjectColumn 'name' => $this->getDisplayName(), 'proxyPHID' => $this->getProxyPHID(), 'project' => $this->getProject()->getRefForConduit(), + 'isHidden' => $this->isHidden(), + 'isDefaultColumn' => $this->isDefaultColumn(), + 'sequence' => (int)$this->getSequence(), ); } From 324470e39b0d4539a7487c2144157d686f5d0906 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 19 Jun 2023 11:55:10 +0200 Subject: [PATCH 23/82] Give embedded image files with transparency a checkered background Summary: Have a consistent rendering experience between File page and file embedded in a task for PNG image files with an alpha channel: Show a checkered background on the embedded image instead of a white background; show full contrast when hovering over the embedded image. Closes T15473 Test Plan: See steps in T15473 - compare an image file embedded in a task before and after applying this patch. - test in Task description - test in Task comment - test in Task comment inside something weird like a table Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15473 Differential Revision: https://we.phorge.it/D25294 --- resources/celerity/map.php | 6 +++--- webroot/rsrc/css/phui/phui-property-list-view.css | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index a7b8a41aa3..277db4a5b7 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '76ed87e3', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => 'f3d35ae0', + 'core.pkg.css' => '8abf4250', 'core.pkg.js' => '2eeda9e0', 'dark-console.pkg.js' => '187792c2', 'differential.pkg.css' => '525f9a1d', @@ -172,7 +172,7 @@ return array( 'rsrc/css/phui/phui-pager.css' => 'd022c7ad', 'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8', 'rsrc/css/phui/phui-policy-section-view.css' => '139fdc64', - 'rsrc/css/phui/phui-property-list-view.css' => '5adf7078', + 'rsrc/css/phui/phui-property-list-view.css' => '118db252', 'rsrc/css/phui/phui-remarkup-preview.css' => '91767007', 'rsrc/css/phui/phui-segment-bar-view.css' => '5166b370', 'rsrc/css/phui/phui-spacing.css' => 'b05cadc3', @@ -875,7 +875,7 @@ return array( 'phui-pager-css' => 'd022c7ad', 'phui-pinboard-view-css' => '1f08f5d8', 'phui-policy-section-view-css' => '139fdc64', - 'phui-property-list-view-css' => '5adf7078', + 'phui-property-list-view-css' => '118db252', 'phui-remarkup-preview-css' => '91767007', 'phui-segment-bar-view-css' => '5166b370', 'phui-spacing-css' => 'b05cadc3', diff --git a/webroot/rsrc/css/phui/phui-property-list-view.css b/webroot/rsrc/css/phui/phui-property-list-view.css index 4d2cbc9b50..93388c3d7c 100644 --- a/webroot/rsrc/css/phui/phui-property-list-view.css +++ b/webroot/rsrc/css/phui/phui-property-list-view.css @@ -204,13 +204,15 @@ div.phui-property-list-stacked .phui-property-list-properties } -.document-engine-image img { +.document-engine-image img, +.phabricator-remarkup-embed-image img { margin: 20px auto; background: url('/rsrc/image/checker_light.png'); max-width: 100%; } -.device-desktop .document-engine-image img:hover { +.device-desktop .document-engine-image img:hover, +.device-desktop .phabricator-remarkup-embed-image img:hover { background: url('/rsrc/image/checker_dark.png'); } From 1c59b65421362da9e7c31f8a3f2177383efece27 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 19 Jun 2023 12:08:19 +0200 Subject: [PATCH 24/82] Dashboards: add capability who can create Dashboards Summary: Add a `dashboard.create` capability to allow limiting dashboard creation (and creation of related panels). This can reduce spam in open Phorge installations in which anyone can create an account while you still want anyone to be able to view existing dashboards. Closes T15438 Test Plan: 1. As an admin, go to `/applications/view/PhabricatorDashboardApplication/` 2. See only two options "Can Use Application: All Users" and "Can Configure Application: Administrators" 3. Apply patch 4. As an admin, go to `/applications/view/PhabricatorDashboardApplication/` and see the new option "Can Create Dashboards" set to "All Users" 5. As an average user, go to `/dashboard/` and successfully create a new Dashboard 6. As an admin, go to `/applications/edit/PhabricatorDashboardApplication/` and change "Can Create Dashboards" from "All Users" to "Administrators", select "Save Policies" button 7. As an average user, go to `/dashboard/` and see that "Create Dashboard" is disabled 8. As an average user, go to an existing dashboard not created by this user and see that selecting "Edit Dashboard" shows "You do not have permission to edit this object." 9. As an average user, go to the existing dashboard that you created yourself and see that the Edit Policy is set to this user. 10. As an average user, go to the existing dashboard that you created yourself and see that you can still create or add panels. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15438 Differential Revision: https://we.phorge.it/D25270 --- src/__phutil_library_map__.php | 2 ++ .../PhabricatorDashboardCreateCapability.php | 16 ++++++++++++++++ .../PhabricatorDashboardApplication.php | 8 ++++++++ .../editor/PhabricatorDashboardEditEngine.php | 5 +++++ 4 files changed, 31 insertions(+) create mode 100644 src/applications/countdown/capability/PhabricatorDashboardCreateCapability.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 17560e11d1..09b8b86da4 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -3081,6 +3081,7 @@ phutil_register_library_map(array( 'PhabricatorDashboardColumn' => 'applications/dashboard/layoutconfig/PhabricatorDashboardColumn.php', 'PhabricatorDashboardConsoleController' => 'applications/dashboard/controller/PhabricatorDashboardConsoleController.php', 'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.php', + 'PhabricatorDashboardCreateCapability' => 'applications/countdown/capability/PhabricatorDashboardCreateCapability.php', 'PhabricatorDashboardDAO' => 'applications/dashboard/storage/PhabricatorDashboardDAO.php', 'PhabricatorDashboardDashboardPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php', 'PhabricatorDashboardDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardDatasource.php', @@ -9496,6 +9497,7 @@ phutil_register_library_map(array( 'PhabricatorDashboardColumn' => 'Phobject', 'PhabricatorDashboardConsoleController' => 'PhabricatorDashboardController', 'PhabricatorDashboardController' => 'PhabricatorController', + 'PhabricatorDashboardCreateCapability' => 'PhabricatorPolicyCapability', 'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO', 'PhabricatorDashboardDashboardPHIDType' => 'PhabricatorPHIDType', 'PhabricatorDashboardDatasource' => 'PhabricatorTypeaheadDatasource', diff --git a/src/applications/countdown/capability/PhabricatorDashboardCreateCapability.php b/src/applications/countdown/capability/PhabricatorDashboardCreateCapability.php new file mode 100644 index 0000000000..c610df069e --- /dev/null +++ b/src/applications/countdown/capability/PhabricatorDashboardCreateCapability.php @@ -0,0 +1,16 @@ + array( + 'default' => PhabricatorPolicies::POLICY_USER, + 'caption' => pht('Default create policy for Dashboards.'), + ), + ); + } } diff --git a/src/applications/dashboard/editor/PhabricatorDashboardEditEngine.php b/src/applications/dashboard/editor/PhabricatorDashboardEditEngine.php index 06b0a3a6fb..84b36fe546 100644 --- a/src/applications/dashboard/editor/PhabricatorDashboardEditEngine.php +++ b/src/applications/dashboard/editor/PhabricatorDashboardEditEngine.php @@ -66,6 +66,11 @@ final class PhabricatorDashboardEditEngine return $object->getURI(); } + protected function getCreateNewObjectPolicy() { + return $this->getApplication()->getPolicy( + PhabricatorDashboardCreateCapability::CAPABILITY); + } + protected function buildCustomEditFields($object) { $layout_options = PhabricatorDashboardLayoutMode::getLayoutModeMap(); From 7c1487e4dcfab19e0ef42cd4596780a37e0c8c4e Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 19 Jun 2023 14:10:29 +0200 Subject: [PATCH 25/82] Fix Pholio RuntimeException: Undefined variable $dictionary (when adding an empty Inline Comment) Summary: Trying to create an empty inline comment in a Pholio mock, `$dictionary` does not get set as both `strlen($v_content)` and `$inline->getID()` are not true. Thus show a more explanatory error message ('Comment cannot be empty.') to users instead of exposing internal variable names. ``` EXCEPTION: (RuntimeException) Undefined variable $dictionary at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=b325304b6e52), phorge(head=master, ref.master=980293b707a0) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/pholio/controller/PholioInlineController.php:117] ``` Closes T15456 Test Plan: After applying this change, try to add an empty Inline Comment in a Pholio mock. See that the error message is now "Comment cannot be empty." instead of "Undefined variable $dictionary". Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15456 Differential Revision: https://we.phorge.it/D25281 --- .../pholio/controller/PholioInlineController.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/applications/pholio/controller/PholioInlineController.php b/src/applications/pholio/controller/PholioInlineController.php index ddced1f9eb..2201e97f74 100644 --- a/src/applications/pholio/controller/PholioInlineController.php +++ b/src/applications/pholio/controller/PholioInlineController.php @@ -102,6 +102,7 @@ final class PholioInlineController extends PholioController { ->addCancelButton($mock_uri, pht('Close')); } + $error = null; if ($request->isFormPost()) { $v_content = $request->getStr('content'); @@ -112,9 +113,13 @@ final class PholioInlineController extends PholioController { } else if ($inline->getID()) { $inline->delete(); $dictionary = array(); + } else { + $error = pht('Comment cannot be empty.'); } - return id(new AphrontAjaxResponse())->setContent($dictionary); + if ($error === null) { + return id(new AphrontAjaxResponse())->setContent($dictionary); + } } switch ($mode) { @@ -151,6 +156,7 @@ final class PholioInlineController extends PholioController { ->setUser($viewer) ->setName('content') ->setLabel(pht('Comment')) + ->setError($error) ->setValue($v_content)); return $this->newDialog() From a25af8ccef69de5978b0904866b028d96732202b Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Fri, 23 Jun 2023 08:48:18 +0200 Subject: [PATCH 26/82] Diviner: add a minimal systemd example Summary: After this change the section "Managing Daemons with phd" mentions a minimally viable systemd configuration file to make systemd-users happier and systemd-haters saddest. Closes T15467 Test Plan: - read the page, see systemd, don't cry Reviewers: O1 Blessed Committers, 20after4 Reviewed By: O1 Blessed Committers, 20after4 Subscribers: 20after4, speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15467 Differential Revision: https://we.phorge.it/D25293 --- .../configuration/managing_daemons.diviner | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/docs/user/configuration/managing_daemons.diviner b/src/docs/user/configuration/managing_daemons.diviner index 0e56a95995..d4af3162a4 100644 --- a/src/docs/user/configuration/managing_daemons.diviner +++ b/src/docs/user/configuration/managing_daemons.diviner @@ -46,6 +46,62 @@ If you want finer-grained control, you can use: NOTE: When you upgrade Phorge or change configuration, you should restart the daemons by running `phd restart`. +Automatically start phd +======================= + +NOTE: If you are opinionated against systemd, cover the eyes of your children +right now!1! + +Computers are good in automatically starting stuff, thanks to the invention +of the "init system". + +Phorge virtually supports any init system. Which one is yours? Don't worry. +If you don't know, it's systemd. + +We propose a minimal systemd configuration file, following some assumptions: + +- your lovely Phorge is installed `/somewhere` +- you have a database service called `mariadb` +- you have a dedicated Unix user called `daemon-user` - coming from + @{article:Diffusion User Guide} + +With the above assumptions, create this configuration file as super-user: + +```lang=ini,name=/etc/systemd/system/phorge-phd.service +[Unit] +Description=Phorge Daemons +Documentation=https://we.phorge.it/book/phorge/article/managing_daemons/ +After=syslog.target network.target mariadb.service + +[Service] +Type=forking +User=daemon-user +Group=daemon-user +ExecStart=/somewhere/phorge/bin/phd start +ExecStop=/somewhere/phorge/bin/phd stop + +[Install] +WantedBy=multi-user.target +``` + +To install this new systemd configuration, execute these commands as +super-user: + +``` +systemctl daemon-reload +systemctl enable --now phorge-phd +``` + +Now the process has started and will survive after any reboot. + +To check if everything is OK: + +``` +systemctl status phorge-phd +``` + +Anything else can be explored in depth by reading the systemd documentation. + = Daemon Console = You can view status and debugging information for daemons in the Daemon Console From e4fe54edf0d368fa87c8b29b293e4ad4e7b14abf Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 26 Jun 2023 14:19:01 +0200 Subject: [PATCH 27/82] Fix typo "recipeint" in metamta.one-mail-per-recipient description Test Plan: Go to `/config/settings/all` and look at the description of `metamta.one-mail-per-recipient` Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Differential Revision: https://we.phorge.it/D25311 --- .../config/option/PhabricatorMetaMTAConfigOptions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php index 36cbd9bd51..7499c978d3 100644 --- a/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php +++ b/src/applications/config/option/PhabricatorMetaMTAConfigOptions.php @@ -227,7 +227,7 @@ EODOC pht( 'Controls whether email for multiple recipients is sent by '. 'creating one message with everyone in the "To:" line, or '. - 'multiple messages that each have a single recipeint in the '. + 'multiple messages that each have a single recipient in the '. '"To:" line.')) ->setDescription($one_mail_per_recipient_desc), $this->newOption('metamta.can-send-as-user', 'bool', false) From 659e13fa6d0e92f129e4c940e765846dd53c9ad4 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Tue, 27 Jun 2023 08:14:29 +0200 Subject: [PATCH 28/82] Fix UX regression in Dashboard Tabs Panel Summary: Before this change, it seems that the Dashboard Tabs Panel could be empty as default. This was the regression: cbc0e661544a31290099ab3d88481bb8d4a3003c The variable $is_selected was defined inside a foreach loop, but that loop was terminated when it was then read again. This redefines that variable in the right scope. | Before | After | |-----------|-----------| | {F312797} | {F312798} | Closes T15474 Test Plan: - see that now you have something visibile in your Dashboard Tabs Panel Reviewers: speck, O1 Blessed Committers Reviewed By: speck, O1 Blessed Committers Subscribers: tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15474, T15146 Differential Revision: https://we.phorge.it/D25291 --- .../dashboard/paneltype/PhabricatorDashboardTabsPanelType.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php b/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php index 54c26dd9d3..831229bab1 100644 --- a/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php +++ b/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php @@ -282,6 +282,8 @@ final class PhabricatorDashboardTabsPanelType $panel_content = pht('(Invalid Panel)'); } + $is_selected = (string)$idx === (string)$selected; + $content_id = celerity_generate_unique_node_id(); $content[] = phutil_tag( From 1005e381604eb51d5bccc4f198d5333eb0ee28e4 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Tue, 27 Jun 2023 13:29:24 +0200 Subject: [PATCH 29/82] Fix notification message when Aphlict is not configured Summary: Before this change the footer in the notification bar was a bit weird on the message "Notification server not enabled": | Before | After | |-----------|-----------| | {F315024} | {F315001} | Also a bit wrong on the "Connecting..." message: | Before | After | |-----------|-----------| | {F315061} | {F315072} | The fix involves a refactor in the HTML structure in order to match the graphic rendered when Aphlict is configured and running. In short, we pass from this: COUNTEREXAMPLE Notification server not enabled To this: Notification server not enabled See the Task for additional details. Closes T15415 Test Plan: Follow the official Notification documentation about the config `notification.servers`, open the Notification top-bar, and check the message in these conditions: - without the config - with the config - with/without Aphlict running https://we.phorge.it/book/phorge/article/notifications/ Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: avivey, speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15415 Differential Revision: https://we.phorge.it/D25312 --- .../PhabricatorNotificationStatusView.php | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/src/applications/notification/view/PhabricatorNotificationStatusView.php b/src/applications/notification/view/PhabricatorNotificationStatusView.php index e962395bba..69939525cc 100644 --- a/src/applications/notification/view/PhabricatorNotificationStatusView.php +++ b/src/applications/notification/view/PhabricatorNotificationStatusView.php @@ -40,34 +40,41 @@ final class PhabricatorNotificationStatusView extends AphrontTagView { protected function getTagContent() { $have = PhabricatorEnv::getEnvConfig('notification.servers'); if ($have) { - $icon = id(new PHUIIconView()) - ->setIcon('fa-circle-o yellow'); - $text = pht('Connecting...'); - return phutil_tag( - 'span', - array( - 'class' => 'connection-status-text '. - 'aphlict-connection-status-connecting', - ), - array( - $icon, - $text, - )); + return $this->buildMessageView( + 'aphlict-connection-status-connecting', + 'fa-circle-o yellow', + pht('Connecting...')); } else { - $text = pht('Notification server not enabled'); - $icon = id(new PHUIIconView()) - ->setIcon('fa-circle-o grey'); - return phutil_tag( - 'span', - array( - 'class' => 'connection-status-text '. - 'aphlict-connection-status-notenabled', - ), - array( - $icon, - $text, - )); + return $this->buildMessageView( + 'aphlict-connection-status-notenabled', + 'fa-circle-o grey', + pht('Notification server not enabled')); } } + /** + * Create an icon and a message. + * + * @param string $class_name Raw CSS class name(s) space separated + * @param string $icon_name Icon name + * @param string $text Text to be shown + * @return array + */ + private function buildMessageView($class_name, $icon_name, $text) { + $icon = id(new PHUIIconView()) + ->setIcon($icon_name); + + $message = phutil_tag( + 'span', + array( + 'class' => 'connection-status-text '.$class_name, + ), + $text); + + return array( + $icon, + $message, + ); + } + } From 8ffa6044626dacaddff8aaa1f291e57135416f0c Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Wed, 28 Jun 2023 23:14:09 +0200 Subject: [PATCH 30/82] Diviner: mention how to flag Arcanist and Phorge as "safe" git repos Summary: This tip is useful if you are affected by the following error in git or similar: fatal: detected dubious ownership in repository at '/var/www/phorge' Just follow the new tip from Diviner to fix at system level. Ref T15282 Test Plan: - see if you like the documentation tip - try to execute the command, and verify that your computer does not explode - eventually visit the /config/ page with and without that change (with and without a /etc/gitconfig) Reviewers: O1 Blessed Committers, avivey, Cigaryno Reviewed By: O1 Blessed Committers, avivey, Cigaryno Subscribers: avivey, speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15282 Differential Revision: https://we.phorge.it/D25236 --- src/docs/user/installation_guide.diviner | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/docs/user/installation_guide.diviner b/src/docs/user/installation_guide.diviner index 1a09a2a3d6..f3c2102059 100644 --- a/src/docs/user/installation_guide.diviner +++ b/src/docs/user/installation_guide.diviner @@ -137,6 +137,12 @@ dependencies: somewhere/ $ git clone https://we.phorge.it/source/arcanist.git somewhere/ $ git clone https://we.phorge.it/source/phorge.git +After cloning, flag them as safe (to avoid the error //"fatal: +detected dubious ownership in repository at ..."//): + + $ sudo git config --system --add safe.directory somewhere/arcanist + $ sudo git config --system --add safe.directory somewhere/phorge + Next Steps ========== From 0a17287e08cd0eea2675ff46efa3135fe6994b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Taavi=20V=C3=A4=C3=A4n=C3=A4nen?= Date: Thu, 29 Jun 2023 14:40:11 +0300 Subject: [PATCH 31/82] Generalize references to PHP 5.x Debian/Ubuntu packages Summary: Both Debian and Ubuntu have been shipping PHP 7.x (or now 8.x) for a while. This patch replaces the versioned php5-foo package references with more general php-foo package names. Test Plan: Navigated to the documentation pages that this patch updates. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Differential Revision: https://we.phorge.it/D25315 --- .../auth/provider/PhabricatorLDAPAuthProvider.php | 2 +- .../config/check/PhabricatorPHPConfigSetupCheck.php | 4 ++-- src/docs/user/configuration/configuration_guide.diviner | 2 +- src/docs/user/field/restarting.diviner | 2 +- src/docs/user/installation_guide.diviner | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php b/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php index d1db832aa2..19f8c625d7 100644 --- a/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php +++ b/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php @@ -264,7 +264,7 @@ final class PhabricatorLDAPAuthProvider extends PhabricatorAuthProvider { 'talk to LDAP. Usually you can install it with '. '`%s`, `%s`, or a similar package manager command.', 'yum install php-ldap', - 'apt-get install php5-ldap')); + 'apt-get install php-ldap')); } } diff --git a/src/applications/config/check/PhabricatorPHPConfigSetupCheck.php b/src/applications/config/check/PhabricatorPHPConfigSetupCheck.php index 09b96d05cf..1862308052 100644 --- a/src/applications/config/check/PhabricatorPHPConfigSetupCheck.php +++ b/src/applications/config/check/PhabricatorPHPConfigSetupCheck.php @@ -83,7 +83,7 @@ final class PhabricatorPHPConfigSetupCheck extends PhabricatorSetupCheck { // NOTE: We're intentionally telling you to install "mysqlnd" here; on // Ubuntu, there's no separate "mysqli" package. - phutil_tag('tt', array(), 'sudo apt-get install php5-mysqlnd')); + phutil_tag('tt', array(), 'sudo apt-get install php-mysqlnd')); $this->newIssue('php.mysqli') ->setName(pht('MySQLi Extension Not Available')) @@ -103,7 +103,7 @@ final class PhabricatorPHPConfigSetupCheck extends PhabricatorSetupCheck { 'native driver is recommended.'. "\n\n". 'You may be able to install the native driver with a command like: %s', - phutil_tag('tt', array(), 'sudo apt-get install php5-mysqlnd')); + phutil_tag('tt', array(), 'sudo apt-get install php-mysqlnd')); $this->newIssue('php.myqlnd') diff --git a/src/docs/user/configuration/configuration_guide.diviner b/src/docs/user/configuration/configuration_guide.diviner index 1fde967a95..c5aa82af86 100644 --- a/src/docs/user/configuration/configuration_guide.diviner +++ b/src/docs/user/configuration/configuration_guide.diviner @@ -139,7 +139,7 @@ server.modules list: Finally, you should run the following commands to enable php support: - $ sudo apt-get install php5-cgi # for Ubuntu; other distros should be similar + $ sudo apt-get install php-cgi # for Ubuntu; other distros should be similar $ sudo lighty-enable-mod fastcgi-php Restart lighttpd after making your edits, then continue below. diff --git a/src/docs/user/field/restarting.diviner b/src/docs/user/field/restarting.diviner index 638e1f1490..8e21c2ac77 100644 --- a/src/docs/user/field/restarting.diviner +++ b/src/docs/user/field/restarting.diviner @@ -112,5 +112,5 @@ like one of these on your system, or a different command: ``` $ sudo /etc/init.d/php-fpm restart -$ sudo service php5-fpm reload +$ sudo service php-fpm reload ``` diff --git a/src/docs/user/installation_guide.diviner b/src/docs/user/installation_guide.diviner index f3c2102059..ec7aa186d2 100644 --- a/src/docs/user/installation_guide.diviner +++ b/src/docs/user/installation_guide.diviner @@ -123,7 +123,7 @@ Here's a general description of what you need to install: - MySQL Server (usually "mysqld" or "mysql-server" or "mariadb-server") - PHP (usually "php") - Required PHP extensions: mbstring, iconv, mysql (or mysqli), curl, pcntl - (these might be something like "php-mysql" or "php5-mysqlnd") + (these might be something like "php-mysql" or "php-mysqlnd") - Optional PHP extensions: gd, zip If you already have LAMP setup, you've probably already got everything you need. From 101ce834b8ad297a6692e62a85717de21bb48ad5 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Fri, 30 Jun 2023 13:17:03 +0100 Subject: [PATCH 32/82] Fix PHP 8.1 strlen() error when database replication Seconds_Behind_Master is NULL Summary: When MySQL database replication is configured, but not running, the slave status Seconds_Behind_Master is NULL. When this value is passed to strlen() an error is thrown. Fixes T15507 Test Plan: * Configure database replication such that Seconds_Behind_Master is NULL * Restart php-fpm * Go to Phorge web site. Reviewers: O1 Blessed Committers, chris Reviewed By: O1 Blessed Committers, chris Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15507 Differential Revision: https://we.phorge.it/D25318 --- src/infrastructure/cluster/PhabricatorDatabaseRef.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/infrastructure/cluster/PhabricatorDatabaseRef.php b/src/infrastructure/cluster/PhabricatorDatabaseRef.php index e526eb1639..0fe2aabbcb 100644 --- a/src/infrastructure/cluster/PhabricatorDatabaseRef.php +++ b/src/infrastructure/cluster/PhabricatorDatabaseRef.php @@ -393,7 +393,7 @@ final class PhabricatorDatabaseRef if ($is_replica) { $latency = idx($replica_status, 'Seconds_Behind_Master'); - if (!strlen($latency)) { + if (!phutil_nonempty_string($latency)) { $ref->setReplicaStatus(self::REPLICATION_NOT_REPLICATING); } else { $latency = (int)$latency; From 73253489bf002f3fd29dba3af3845cb4938fbf56 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Fri, 30 Jun 2023 14:34:41 +0100 Subject: [PATCH 33/82] Make src/infrastructure/javelin/markup.php phabricator_form PHP 8.1 compliant Summary: src/infrastructure/javelin/markup.php phabricator_form() performs a strcasecmp() operation on an optional attribute withoiut checking to see if it exists first. This causes an 'Passing null to parameter #1 ($string1) of type string is deprecated' error. Because we subsequenly check to see that the value equals /POST/i, all we need to do is check that the value has some 'true' value before doing the strcasecmp(). If it's not true, then it won't be POST! Fixes T15509 Test Plan: View a diff. Eg: https://my.phorge.site/D1234 Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15509 Differential Revision: https://we.phorge.it/D25319 --- src/infrastructure/javelin/markup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/infrastructure/javelin/markup.php b/src/infrastructure/javelin/markup.php index 8a040031cc..285f027d3d 100644 --- a/src/infrastructure/javelin/markup.php +++ b/src/infrastructure/javelin/markup.php @@ -74,7 +74,7 @@ function phabricator_form(PhabricatorUser $user, $attributes, $content) { $body = array(); $http_method = idx($attributes, 'method'); - $is_post = (strcasecmp($http_method, 'POST') === 0); + $is_post = $http_method && (strcasecmp($http_method, 'POST') === 0); $http_action = idx($attributes, 'action'); From aebd7a2f7239c025f65171065e3fab54bdb98200 Mon Sep 17 00:00:00 2001 From: MacFan4000 Date: Thu, 29 Jun 2023 19:21:54 -0400 Subject: [PATCH 34/82] Update a couple of lingering instances of secure.phabricator.com to we.phorge.it Summary: We were still pointint to secure.phabricator.com in a couple places. This fixes that. Test Plan: No testing needed Reviewers: O1 Blessed Committers, speck, Cigaryno Reviewed By: O1 Blessed Committers, speck, Cigaryno Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Differential Revision: https://we.phorge.it/D25316 --- src/applications/diviner/controller/DivinerMainController.php | 2 +- src/view/widget/AphrontStackTraceView.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/diviner/controller/DivinerMainController.php b/src/applications/diviner/controller/DivinerMainController.php index 21450698e6..791e7520b6 100644 --- a/src/applications/diviner/controller/DivinerMainController.php +++ b/src/applications/diviner/controller/DivinerMainController.php @@ -50,7 +50,7 @@ final class DivinerMainController extends DivinerController { $text = pht( "(NOTE) **Looking for documentation?** ". "If you're looking for help and information about %s, ". - "you can [[https://secure.phabricator.com/diviner/ | ". + "you can [[https://we.phorge.it/diviner/ | ". "browse the public %s documentation]] on the live site.\n\n". "Diviner is the documentation generator used to build this ". "documentation.\n\n". diff --git a/src/view/widget/AphrontStackTraceView.php b/src/view/widget/AphrontStackTraceView.php index ff8cac43bc..15b39be878 100644 --- a/src/view/widget/AphrontStackTraceView.php +++ b/src/view/widget/AphrontStackTraceView.php @@ -15,7 +15,7 @@ final class AphrontStackTraceView extends AphrontView { $libraries = PhutilBootloader::getInstance()->getAllLibraries(); // TODO: Make this configurable? - $path = 'https://secure.phabricator.com/diffusion/%s/browse/master/src/'; + $path = 'https://we.phorge.it/diffusion/%s/browse/master/src/'; $callsigns = array( 'arcanist' => 'ARC', From 9aafbb42ef8d33437696c4b55fc24ea1de0a3da9 Mon Sep 17 00:00:00 2001 From: Aviv Eyal Date: Sun, 2 Jul 2023 08:47:59 -0700 Subject: [PATCH 35/82] fix strlen in PhabricatorMailManagementShowOutboundWorkflow Summary: Ref T15064 Test Plan: run `./bin/mail show-outbound --id 1` on a non-html email with php 8.1, no crash. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Tags: #php_8_support Maniphest Tasks: T15064 Differential Revision: https://we.phorge.it/D25275 --- .../PhabricatorMailManagementSendTestWorkflow.php | 5 +---- .../PhabricatorMailManagementShowOutboundWorkflow.php | 6 +++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php b/src/applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php index f390ff27df..6ea2c9de5a 100644 --- a/src/applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php +++ b/src/applications/metamta/management/PhabricatorMailManagementSendTestWorkflow.php @@ -63,6 +63,7 @@ final class PhabricatorMailManagementSendTestWorkflow array( 'name' => 'type', 'param' => 'message-type', + 'default' => PhabricatorMailEmailMessage::MESSAGETYPE, 'help' => pht( 'Send the specified type of message (email, sms, ...).'), ), @@ -74,10 +75,6 @@ final class PhabricatorMailManagementSendTestWorkflow $viewer = $this->getViewer(); $type = $args->getArg('type'); - if (!strlen($type)) { - $type = PhabricatorMailEmailMessage::MESSAGETYPE; - } - $type_map = PhabricatorMailExternalMessage::getAllMessageTypes(); if (!isset($type_map[$type])) { throw new PhutilArgumentUsageException( diff --git a/src/applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php b/src/applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php index f29a63c2eb..1f4f5a3e2a 100644 --- a/src/applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php +++ b/src/applications/metamta/management/PhabricatorMailManagementShowOutboundWorkflow.php @@ -65,7 +65,7 @@ final class PhabricatorMailManagementShowOutboundWorkflow foreach ($messages as $message_key => $message) { if ($args->getArg('dump-html')) { $html_body = $message->getHTMLBody(); - if (strlen($html_body)) { + if (phutil_nonempty_string($html_body)) { $template = "{$html_body}"; $console->writeOut("%s\n", $html_body); @@ -188,7 +188,7 @@ final class PhabricatorMailManagementShowOutboundWorkflow $info[] = null; $info[] = $this->newSectionHeader(pht('TEXT BODY')); - if (strlen($message->getBody())) { + if (phutil_nonempty_string($message->getBody())) { $info[] = tsprintf('%B', $message->getBody()); } else { $info[] = pht('(This message has no text body.)'); @@ -203,7 +203,7 @@ final class PhabricatorMailManagementShowOutboundWorkflow $info[] = null; $info[] = $this->newSectionHeader(pht('HTML BODY')); - if (strlen($message->getHTMLBody())) { + if (phutil_nonempty_string($message->getHTMLBody())) { $info[] = $message->getHTMLBody(); $info[] = null; } else { From d725ffaa7728bdbcd07870e9e8f4d244eb9dcf41 Mon Sep 17 00:00:00 2001 From: Aviv Eyal Date: Sun, 2 Jul 2023 08:48:51 -0700 Subject: [PATCH 36/82] Fix "Register with Approval flow" for php 8 Summary: Ref T15064. Test Plan: - Register as a new user - as admin, view user's page and approve it - As new user, hit "wait patiently" to go back to Home No crashes in this flow. Reviewers: O1 Blessed Committers, chris Reviewed By: O1 Blessed Committers, chris Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15064 Differential Revision: https://we.phorge.it/D25317 --- .../auth/controller/PhabricatorAuthNeedsApprovalController.php | 2 +- src/applications/auth/engine/PhabricatorAuthPasswordEngine.php | 2 ++ .../customfield/standard/PhabricatorStandardCustomField.php | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/applications/auth/controller/PhabricatorAuthNeedsApprovalController.php b/src/applications/auth/controller/PhabricatorAuthNeedsApprovalController.php index 1121dfb14a..b098a07ddd 100644 --- a/src/applications/auth/controller/PhabricatorAuthNeedsApprovalController.php +++ b/src/applications/auth/controller/PhabricatorAuthNeedsApprovalController.php @@ -51,7 +51,7 @@ final class PhabricatorAuthNeedsApprovalController $viewer, PhabricatorAuthWaitForApprovalMessageType::MESSAGEKEY); - if (!strlen($text)) { + if (!phutil_nonempty_string($text)) { return null; } diff --git a/src/applications/auth/engine/PhabricatorAuthPasswordEngine.php b/src/applications/auth/engine/PhabricatorAuthPasswordEngine.php index a1fec4a6d2..0efb1fe4fc 100644 --- a/src/applications/auth/engine/PhabricatorAuthPasswordEngine.php +++ b/src/applications/auth/engine/PhabricatorAuthPasswordEngine.php @@ -150,6 +150,8 @@ final class PhabricatorAuthPasswordEngine $base_uri = new PhutilURI($base_uri); $blocklist[] = $base_uri->getDomain(); + $blocklist = array_filter($blocklist); + // Generate additional subterms by splitting the raw blocklist on // characters like "@", " " (space), and "." to break up email addresses, // readable names, and domain names into components. diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php index c41148a4aa..37f9e808ab 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php @@ -301,7 +301,7 @@ abstract class PhabricatorStandardCustomField } public function renderPropertyViewValue(array $handles) { - if (!strlen($this->getFieldValue())) { + if (!phutil_nonempty_string($this->getFieldValue())) { return null; } return $this->getFieldValue(); From 603cf474ee1d098ae9e4107d4fefdf1cacc71475 Mon Sep 17 00:00:00 2001 From: Aviv Eyal Date: Mon, 3 Jul 2023 13:46:25 -0700 Subject: [PATCH 37/82] Fix int fields for now Summary: Fix T15516 Test Plan: Viewed an "int" custom field, no boom. Reviewers: speck, valerio.bozzolan, O1 Blessed Committers Reviewed By: valerio.bozzolan, O1 Blessed Committers Subscribers: tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15516 Differential Revision: https://we.phorge.it/D25325 --- .../standard/PhabricatorStandardCustomField.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php index 37f9e808ab..373aa9b66a 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php @@ -301,10 +301,14 @@ abstract class PhabricatorStandardCustomField } public function renderPropertyViewValue(array $handles) { - if (!phutil_nonempty_string($this->getFieldValue())) { - return null; + // If your field needs to render anything more complicated then a string, + // then you should override this method. + $value_str = phutil_string_cast($this->getFieldValue()); + + if (phutil_nonempty_string($value_str)) { + return $value_str; } - return $this->getFieldValue(); + return null; } public function shouldAppearInApplicationSearch() { From 4a0d3ba3e14b65ae88131c87e1b1ce0dd9b927c8 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Tue, 4 Jul 2023 17:10:19 +0200 Subject: [PATCH 38/82] Locate File: allow to search './path/to/something.txt' Summary: Before this change, if you search a file using Locate File, this was the only accepted syntax for a full-path: path/to/something.txt After this change, some relative/absolute Unix-like variants are also accepted: ./path/to/something.txt /path/to/something.txt Similar prefixes can be frequent when you quickly copy-paste things from shell commands like 'grep' or 'find' etc. Ref T15508 Test Plan: Visit a lovely repository like Phorge and use Locate File with these: 1. src/applications/maniphest/editor/ManiphestEditEngine.php 2. /src/applications/maniphest/editor/ManiphestEditEngine.php 3. ./src/applications/maniphest/editor/ManiphestEditEngine.php After this change, also 2. and 3. return the expected file. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: avivey, speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15508 Differential Revision: https://we.phorge.it/D25320 --- resources/celerity/map.php | 16 ++++++++-------- .../diffusion/DiffusionLocateFileSource.js | 4 ++++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 277db4a5b7..0f0ee9d3f4 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -387,7 +387,7 @@ return array( 'rsrc/js/application/diff/DiffTreeView.js' => '5d83623b', 'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd', 'rsrc/js/application/differential/behavior-populate.js' => 'b86ef6c2', - 'rsrc/js/application/diffusion/DiffusionLocateFileSource.js' => '94243d89', + 'rsrc/js/application/diffusion/DiffusionLocateFileSource.js' => '6c798a10', 'rsrc/js/application/diffusion/ExternalEditorLinkEngine.js' => '48a8641f', 'rsrc/js/application/diffusion/behavior-audit-preview.js' => 'b7b73831', 'rsrc/js/application/diffusion/behavior-commit-branches.js' => '4b671572', @@ -707,7 +707,7 @@ return array( 'javelin-chart-function-label' => '81de1dab', 'javelin-color' => '78f811c9', 'javelin-cookie' => '05d290ef', - 'javelin-diffusion-locate-file-source' => '94243d89', + 'javelin-diffusion-locate-file-source' => '6c798a10', 'javelin-dom' => 'e4c7622a', 'javelin-dynval' => '202a2e85', 'javelin-event' => 'c03f2fb4', @@ -1555,6 +1555,12 @@ return array( 'phabricator-textareautils', 'phabricator-remarkup-metadata', ), + '6c798a10' => array( + 'javelin-install', + 'javelin-dom', + 'javelin-typeahead-preloaded-source', + 'javelin-util', + ), '6cfa0008' => array( 'javelin-dom', 'javelin-dynval', @@ -1762,12 +1768,6 @@ return array( 'phabricator-prefab', 'javelin-json', ), - '94243d89' => array( - 'javelin-install', - 'javelin-dom', - 'javelin-typeahead-preloaded-source', - 'javelin-util', - ), '9623adc1' => array( 'javelin-behavior', 'javelin-stratcom', diff --git a/webroot/rsrc/js/application/diffusion/DiffusionLocateFileSource.js b/webroot/rsrc/js/application/diffusion/DiffusionLocateFileSource.js index 1f94f349d3..3a3bcb9bce 100644 --- a/webroot/rsrc/js/application/diffusion/DiffusionLocateFileSource.js +++ b/webroot/rsrc/js/application/diffusion/DiffusionLocateFileSource.js @@ -99,6 +99,10 @@ JX.install('DiffusionLocateFileSource', { return []; } + // Be nice with terminal users that may have "./" or "/" prefixes. + // Otherwise, not a single result is returned. + search = search.replace(/^\.?\//, ''); + // We know that the results for "abc" are always a subset of the results // for "a" and "ab" -- and there's a good chance we already computed // those result sets. Find the longest cached result which is a prefix From 80484b76a5ff815a4f4849e2899fe39650bcd560 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Tue, 4 Jul 2023 17:14:23 +0200 Subject: [PATCH 39/82] Remarkup Code-block: parse language specifier in markdown Summary: We add support to code blocks with the language expressed as GitLab/GitHub/StackOverflow/... "flavored markdown". So we support this syntax: (to avoid confusion see it online on the Diff) lang=text ```php $asd = 1; ``` Before this change, this was the only supposed syntax in Remarkup, with an explicit "lang=": lang=text ```lang=php $asd = 1; ``` This change introduces a minor risk to eat legitimate Remarkup content, since Remarkup allows to do a multi-line in this way: lang=text ```$asd = 1; $asd = 2;``` The above example still works, but, there is a chance that hardcore Remarkup people have a problem when doing a code block to mention programming languages. In short, this can be problematic since "cpp" will be eaten from this list: COUNTEREXAMPLE ```cpp php python ``` Using the above example is not socially nice because it is not usable in GitLab, GitHub and Stack Overflow. If your first line is eaten: Just *add* a newline on the top to reach a valid raw Markdown list (suggested, valid in Remarkup + Markdown): lang=text ``` cpp php python ``` Or, just add "text" to specify that as language (suggested, valid in Remarkup + Markdown): lang=text ```text cpp php python ``` Or, just *remove* a newline from the bottom to reach a valid raw Remarkup list (Remarkup-only): lang=text ```cpp php python``` Or, just specify that you are writing in the language "text" (Remarkup-only): lang=text ```lang=text cpp php python``` To reduce impact and help you, the logic of this strict implementation is: - must have backticks - must not have any valid remarkup option, like lang=, counterexample, etc. - must not have content in the same line of the last backticks - must have a known language in our proposed subset If everything is OK, we remove that language from the content since it would be otherwise displayed. Interestingly, this could improve performance when rendering README files or snippets from external websites, since - in case - we do not need to guess the language using our deep dark magic. Closes T15481 Test Plan: We added some nice unit tests. Ensure that this test passes: PhutilRemarkupEngineTestCase::testEngine Optionally, take vision of these, before and after: https://we.phorge.it/P16 Change the test plan slightly every time, to make sure it is not in your cache. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: avivey, speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15481 Differential Revision: https://we.phorge.it/D25299 --- .../blockrule/PhutilRemarkupCodeBlockRule.php | 102 +++++++++++++++++- .../PhutilRemarkupEngineTestCase.php | 2 + .../remarkup/tick-block-flavored.txt | 7 ++ .../tick-block-multi-flavored-comment.txt | 18 ++++ .../tick-block-multi-flavored-empty.txt | 9 ++ .../remarkup/tick-block-multi-flavored.txt | 20 ++++ 6 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-flavored.txt create mode 100644 src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored-comment.txt create mode 100644 src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored-empty.txt create mode 100644 src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored.txt diff --git a/src/infrastructure/markup/blockrule/PhutilRemarkupCodeBlockRule.php b/src/infrastructure/markup/blockrule/PhutilRemarkupCodeBlockRule.php index b8fef85b98..8b23fe6541 100644 --- a/src/infrastructure/markup/blockrule/PhutilRemarkupCodeBlockRule.php +++ b/src/infrastructure/markup/blockrule/PhutilRemarkupCodeBlockRule.php @@ -44,7 +44,18 @@ final class PhutilRemarkupCodeBlockRule extends PhutilRemarkupBlockRule { } public function markupText($text, $children) { - if (preg_match('/^\s*```/', $text)) { + // Header/footer eventually useful to be nice with "flavored markdown". + // When it starts with ```stuff the header is 'stuff' (->language) + // When it ends with stuff``` the footer is 'stuff' (->garbage) + $header_line = null; + $footer_line = null; + + $matches = null; + if (preg_match('/^\s*```(.*)/', $text, $matches)) { + if (isset($matches[1])) { + $header_line = $matches[1]; + } + // If this is a ```-style block, trim off the backticks and any leading // blank line. $text = preg_replace('/^\s*```(\s*\n)?/', '', $text); @@ -52,6 +63,13 @@ final class PhutilRemarkupCodeBlockRule extends PhutilRemarkupBlockRule { } $lines = explode("\n", $text); + + // If we have a flavored header, it has sense to look for the footer. + if ($header_line !== null && $lines) { + $footer_line = $lines[last_key($lines)]; + } + + // Strip final empty lines while ($lines && !strlen(last($lines))) { unset($lines[last_key($lines)]); } @@ -65,20 +83,39 @@ final class PhutilRemarkupCodeBlockRule extends PhutilRemarkupBlockRule { $parser = new PhutilSimpleOptions(); $custom = $parser->parse(head($lines)); + $valid_options = null; if ($custom) { - $valid = true; + $valid_options = true; foreach ($custom as $key => $value) { if (!array_key_exists($key, $options)) { - $valid = false; + $valid_options = false; break; } } - if ($valid) { + if ($valid_options) { array_shift($lines); $options = $custom + $options; } } + // Parse flavored markdown strictly to don't eat legitimate Remarkup. + // Proceed only if we tried to parse options and we failed + // (no options also mean no language). + // For example this is not a valid option: ```php + // Proceed only if the footer exists and it is not: blabla``` + // Accept only 2 lines or more. First line: header; then content. + if ( + $valid_options === false && + $header_line !== null && + $footer_line === '' && + count($lines) > 1 + ) { + if (self::isKnownLanguageCode($header_line)) { + array_shift($lines); + $options['lang'] = $header_line; + } + } + // Normalize the text back to a 0-level indent. $min_indent = 80; foreach ($lines as $line) { @@ -249,4 +286,61 @@ final class PhutilRemarkupCodeBlockRule extends PhutilRemarkupBlockRule { $engine->highlightSource($options['lang'], $text))); } + /** + * Check if a language code can be used in a generic flavored markdown. + * @param string $lang Language code + * @return bool + */ + private static function isKnownLanguageCode($lang) { + $languages = self::knownLanguageCodes(); + return isset($languages[$lang]); + } + + /** + * Get the available languages for a generic flavored markdown. + * @return array Languages as array keys. Ignore the value. + */ + private static function knownLanguageCodes() { + // This is a friendly subset from https://pygments.org/languages/ + static $map = array( + 'arduino' => 1, + 'assembly' => 1, + 'awk' => 1, + 'bash' => 1, + 'bat' => 1, + 'c' => 1, + 'cmake' => 1, + 'cobol' => 1, + 'cpp' => 1, + 'css' => 1, + 'csharp' => 1, + 'dart' => 1, + 'delphi' => 1, + 'fortran' => 1, + 'go' => 1, + 'groovy' => 1, + 'haskell' => 1, + 'java' => 1, + 'javascript' => 1, + 'kotlin' => 1, + 'lisp' => 1, + 'lua' => 1, + 'matlab' => 1, + 'make' => 1, + 'perl' => 1, + 'php' => 1, + 'powershell' => 1, + 'python' => 1, + 'r' => 1, + 'ruby' => 1, + 'rust' => 1, + 'scala' => 1, + 'sh' => 1, + 'sql' => 1, + 'typescript' => 1, + 'vba' => 1, + ); + return $map; + } + } diff --git a/src/infrastructure/markup/remarkup/__tests__/PhutilRemarkupEngineTestCase.php b/src/infrastructure/markup/remarkup/__tests__/PhutilRemarkupEngineTestCase.php index c3b4960d0c..38831d034a 100644 --- a/src/infrastructure/markup/remarkup/__tests__/PhutilRemarkupEngineTestCase.php +++ b/src/infrastructure/markup/remarkup/__tests__/PhutilRemarkupEngineTestCase.php @@ -2,6 +2,8 @@ /** * Test cases for @{class:PhutilRemarkupEngine}. + * @TODO: This unit is not always triggered when you need it. + * https://we.phorge.it/T15500 */ final class PhutilRemarkupEngineTestCase extends PhutilTestCase { diff --git a/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-flavored.txt b/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-flavored.txt new file mode 100644 index 0000000000..f224942b1d --- /dev/null +++ b/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-flavored.txt @@ -0,0 +1,7 @@ +```cpp +code +``` +~~~~~~~~~~ +

+~~~~~~~~~~ + code diff --git a/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored-comment.txt b/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored-comment.txt new file mode 100644 index 0000000000..bcdaca8063 --- /dev/null +++ b/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored-comment.txt @@ -0,0 +1,18 @@ +```#comment +code + +#more comment +more code``` + +~~~~~~~~~~ +
#comment
+code
+
+#more comment
+more code
+~~~~~~~~~~ + #comment + code + + #more comment + more code diff --git a/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored-empty.txt b/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored-empty.txt new file mode 100644 index 0000000000..c05d44ec0f --- /dev/null +++ b/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored-empty.txt @@ -0,0 +1,9 @@ +``` +cpp +second line``` +~~~~~~~~~~ +
cpp
+second line
+~~~~~~~~~~ + cpp + second line diff --git a/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored.txt b/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored.txt new file mode 100644 index 0000000000..5dc2cef421 --- /dev/null +++ b/src/infrastructure/markup/remarkup/__tests__/remarkup/tick-block-multi-flavored.txt @@ -0,0 +1,20 @@ +```cpp +code + +more code + +more code +``` + +~~~~~~~~~~ +
code
+
+more code
+
+more code
+~~~~~~~~~~ + code + + more code + + more code From 5e48e16f77fd918607cb943f1b1f78293bb00cee Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Tue, 4 Jul 2023 16:24:12 +0100 Subject: [PATCH 40/82] Update DiffusionDocumentRenderingEngine to cope with null code coverage in PHP 8.1 Summary: Update DiffusionDocumentRenderingEngine to cope with null code coverage in PHP 8.1 Fixes T15523 Test Plan: https://my.phorge.site/source/myrepo/browse/master/myfile Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15523 Differential Revision: https://we.phorge.it/D25330 --- .../diffusion/document/DiffusionDocumentRenderingEngine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/diffusion/document/DiffusionDocumentRenderingEngine.php b/src/applications/diffusion/document/DiffusionDocumentRenderingEngine.php index 800d195726..2c33a82ad5 100644 --- a/src/applications/diffusion/document/DiffusionDocumentRenderingEngine.php +++ b/src/applications/diffusion/document/DiffusionDocumentRenderingEngine.php @@ -87,7 +87,7 @@ final class DiffusionDocumentRenderingEngine $ref->setSymbolMetadata($this->getSymbolMetadata()); $coverage = $drequest->loadCoverage(); - if (strlen($coverage)) { + if (phutil_nonempty_string($coverage)) { $ref->addCoverage($coverage); } } From 9bf5e1735287f6f4113040fa5eb763e20d94906d Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Tue, 4 Jul 2023 12:01:51 +0100 Subject: [PATCH 41/82] PHP8.1 fix for DiffusionServeController serveRequest() Summary: When a 'git pull' is done to an https git URL, the $_SERVER variables PHP_AUTH_USER and PHP_AUTH_PW will be unset, causing PHP 8.1 to throw strlen(null) errors. This update fixes the issue by defaulting the values to '', which results in $have_user and $have_pass having false values as desired. Fixes T15520 Test Plan: arc unit Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15520 Differential Revision: https://we.phorge.it/D25327 --- src/__phutil_library_map__.php | 2 ++ .../controller/DiffusionServeController.php | 4 ++-- .../DiffusionServeControllerTestCase.php | 21 +++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/applications/diffusion/controller/__tests__/DiffusionServeControllerTestCase.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 09b8b86da4..3de392e025 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1052,6 +1052,7 @@ phutil_register_library_map(array( 'DiffusionSSHWorkflow' => 'applications/diffusion/ssh/DiffusionSSHWorkflow.php', 'DiffusionSearchQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionSearchQueryConduitAPIMethod.php', 'DiffusionServeController' => 'applications/diffusion/controller/DiffusionServeController.php', + 'DiffusionServeControllerTestCase' => 'applications/diffusion/controller/__tests__/DiffusionServeControllerTestCase.php', 'DiffusionServiceRef' => 'applications/diffusion/ref/DiffusionServiceRef.php', 'DiffusionSetPasswordSettingsPanel' => 'applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php', 'DiffusionSetupException' => 'applications/diffusion/exception/DiffusionSetupException.php', @@ -7103,6 +7104,7 @@ phutil_register_library_map(array( 'DiffusionSSHWorkflow' => 'PhabricatorSSHWorkflow', 'DiffusionSearchQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', 'DiffusionServeController' => 'DiffusionController', + 'DiffusionServeControllerTestCase' => 'PhabricatorTestCase', 'DiffusionServiceRef' => 'Phobject', 'DiffusionSetPasswordSettingsPanel' => 'PhabricatorSettingsPanel', 'DiffusionSetupException' => 'Exception', diff --git a/src/applications/diffusion/controller/DiffusionServeController.php b/src/applications/diffusion/controller/DiffusionServeController.php index 89430eef37..93656ea607 100644 --- a/src/applications/diffusion/controller/DiffusionServeController.php +++ b/src/applications/diffusion/controller/DiffusionServeController.php @@ -183,8 +183,8 @@ final class DiffusionServeController extends DiffusionController { // won't prompt users who provide a username but no password otherwise. // See T10797 for discussion. - $have_user = strlen(idx($_SERVER, 'PHP_AUTH_USER')); - $have_pass = strlen(idx($_SERVER, 'PHP_AUTH_PW')); + $have_user = strlen(idx($_SERVER, 'PHP_AUTH_USER', '')); + $have_pass = strlen(idx($_SERVER, 'PHP_AUTH_PW', '')); if ($have_user && $have_pass) { $username = $_SERVER['PHP_AUTH_USER']; $password = new PhutilOpaqueEnvelope($_SERVER['PHP_AUTH_PW']); diff --git a/src/applications/diffusion/controller/__tests__/DiffusionServeControllerTestCase.php b/src/applications/diffusion/controller/__tests__/DiffusionServeControllerTestCase.php new file mode 100644 index 0000000000..67c5e63a57 --- /dev/null +++ b/src/applications/diffusion/controller/__tests__/DiffusionServeControllerTestCase.php @@ -0,0 +1,21 @@ + true, + ); + } + + public function testHandleRequest() { + $aphront_request = new AphrontRequest('example.com', '/'); + $diffusion_serve_controller = new DiffusionServeController(); + + $diffusion_serve_controller->setRequest($aphront_request); + $result = $diffusion_serve_controller->handleRequest($aphront_request); + $this->assertTrue(true, 'handleRequest did not throw an error'); + $this->assertTrue($result instanceof PhabricatorVCSResponse, + 'handleRequest() returns PhabricatorVCSResponse object'); + } + +} From 9d512595c0e2a37bb50097f3494af806b8322d45 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Wed, 5 Jul 2023 14:24:47 +0100 Subject: [PATCH 42/82] Fix PHP 8.1 DifferentialBranchField getBranchDescription strlen(null) error Summary: Fix PHP 8.1 strlen(null) error in DifferentialBranchField getBranchDescription() Fixes T15531 Test Plan: Simply viewing a diff (eg https://my.phorge.site/D1234) on a PHP 8.1 server generated the error fixed by this diff. Also created a unit test. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15531 Differential Revision: https://we.phorge.it/D25335 --- src/__phutil_library_map__.php | 2 + .../customfield/DifferentialBranchField.php | 2 +- .../DifferentialBranchFieldTestCase.php | 39 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/applications/differential/customfield/__tests__/DifferentialBranchFieldTestCase.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 3de392e025..ddee83b5f1 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -466,6 +466,7 @@ phutil_register_library_map(array( 'DifferentialBlockHeraldAction' => 'applications/differential/herald/DifferentialBlockHeraldAction.php', 'DifferentialBlockingReviewerDatasource' => 'applications/differential/typeahead/DifferentialBlockingReviewerDatasource.php', 'DifferentialBranchField' => 'applications/differential/customfield/DifferentialBranchField.php', + 'DifferentialBranchFieldTestCase' => 'applications/differential/customfield/__tests__/DifferentialBranchFieldTestCase.php', 'DifferentialBuildableEngine' => 'applications/differential/harbormaster/DifferentialBuildableEngine.php', 'DifferentialChangeDetailMailView' => 'applications/differential/mail/DifferentialChangeDetailMailView.php', 'DifferentialChangeHeraldFieldGroup' => 'applications/differential/herald/DifferentialChangeHeraldFieldGroup.php', @@ -6472,6 +6473,7 @@ phutil_register_library_map(array( 'DifferentialBlockHeraldAction' => 'HeraldAction', 'DifferentialBlockingReviewerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'DifferentialBranchField' => 'DifferentialCustomField', + 'DifferentialBranchFieldTestCase' => 'PhabricatorTestCase', 'DifferentialBuildableEngine' => 'HarbormasterBuildableEngine', 'DifferentialChangeDetailMailView' => 'DifferentialMailView', 'DifferentialChangeHeraldFieldGroup' => 'HeraldFieldGroup', diff --git a/src/applications/differential/customfield/DifferentialBranchField.php b/src/applications/differential/customfield/DifferentialBranchField.php index 60291b6be3..9d5d8f81a9 100644 --- a/src/applications/differential/customfield/DifferentialBranchField.php +++ b/src/applications/differential/customfield/DifferentialBranchField.php @@ -45,7 +45,7 @@ final class DifferentialBranchField return pht('%s (bookmark)', $bookmark); } else if (strlen($branch)) { $onto = $diff->loadTargetBranch(); - if (strlen($onto) && ($onto !== $branch)) { + if (phutil_nonempty_string($onto) && ($onto !== $branch)) { return pht( '%s (branched from %s)', $branch, diff --git a/src/applications/differential/customfield/__tests__/DifferentialBranchFieldTestCase.php b/src/applications/differential/customfield/__tests__/DifferentialBranchFieldTestCase.php new file mode 100644 index 0000000000..e96b4bd245 --- /dev/null +++ b/src/applications/differential/customfield/__tests__/DifferentialBranchFieldTestCase.php @@ -0,0 +1,39 @@ + true, + ); + } + + private function getTestDiff() { + $parser = new ArcanistDiffParser(); + $raw_diff = <<parseDiff($raw_diff)); + } + + public function testRenderDiffPropertyViewValue() { + $test_object = new DifferentialBranchField(); + $diff = $this->getTestDiff(); + $diff->setBranch('test'); + $this->assertEqual('test', + $test_object->renderDiffPropertyViewValue($diff)); + } +} From f45d6421a13cd3cbec21b0be5fbedc5c04605d96 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Wed, 5 Jul 2023 19:36:56 +0200 Subject: [PATCH 43/82] Fix PHP 8.1 "strlen(null)" exception opening a File overlay (Lightbox comment frame) Summary: The error was caused by the overlay lightbox, since it gives the possibility to share a comment on any file in any general Remarkup text, but that comment textarea is indeed empty as default. `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=T15498, ref.master=a25af8ccef69, ref.T15498=a25af8ccef69) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/files/controller/PhabricatorFileLightboxController.php:23] ``` Closes T15498 Test Plan: Visit a blog post with a file/image dropped in the content and click on the thumbnail. No error overlay dialog is displayed anymore. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15498 Differential Revision: https://we.phorge.it/D25310 --- .../files/controller/PhabricatorFileLightboxController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/files/controller/PhabricatorFileLightboxController.php b/src/applications/files/controller/PhabricatorFileLightboxController.php index 59a826dd42..28123d9002 100644 --- a/src/applications/files/controller/PhabricatorFileLightboxController.php +++ b/src/applications/files/controller/PhabricatorFileLightboxController.php @@ -20,7 +20,7 @@ final class PhabricatorFileLightboxController return new Aphront404Response(); } - if (strlen($comment)) { + if (phutil_nonempty_string($comment)) { $xactions = array(); $xactions[] = id(new PhabricatorFileTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) From 71f38a90a3582aff885a18a1ae9d3f0ffe766aa4 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Wed, 5 Jul 2023 19:40:53 +0200 Subject: [PATCH 44/82] Fix PHP 8.1 "strlen(null)" exception on History page of Diffusion repo after setting maintenance mode Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=master, ref.master=1c098c273d06) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/repository/xaction/PhabricatorRepositoryMaintenanceTransaction.php:28] ``` Closes T15475 Test Plan: Play a bit with maintenance messages: ./bin/repository maintenance --start "Start" R1 ./bin/repository maintenance --start "Start Yeah" R1 ./bin/repository maintenance --stop R1 Then visit `/diffusion/1/manage/history/` and look at `Diffusion put this repository into maintenance mode.` as expected, instead of an exception. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15475 Differential Revision: https://we.phorge.it/D25295 --- .../PhabricatorRepositoryMaintenanceTransaction.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/applications/repository/xaction/PhabricatorRepositoryMaintenanceTransaction.php b/src/applications/repository/xaction/PhabricatorRepositoryMaintenanceTransaction.php index caf9e84527..c1259aa983 100644 --- a/src/applications/repository/xaction/PhabricatorRepositoryMaintenanceTransaction.php +++ b/src/applications/repository/xaction/PhabricatorRepositoryMaintenanceTransaction.php @@ -25,11 +25,14 @@ final class PhabricatorRepositoryMaintenanceTransaction $old = $this->getOldValue(); $new = $this->getNewValue(); - if (strlen($old) && !strlen($new)) { + $old_nonempty = phutil_nonempty_string($old); + $new_nonempty = phutil_nonempty_string($new); + + if ($old_nonempty && !$new_nonempty) { return pht( '%s took this repository out of maintenance mode.', $this->renderAuthor()); - } else if (!strlen($old) && strlen($new)) { + } else if (!$old_nonempty && $new_nonempty) { return pht( '%s put this repository into maintenance mode.', $this->renderAuthor()); From d5a28e12a005e7082dab685dd6e615da5213db33 Mon Sep 17 00:00:00 2001 From: Aviv Eyal Date: Wed, 5 Jul 2023 13:28:12 -0700 Subject: [PATCH 45/82] Project Hovercards: Show Description Summary: Fixes T15275. Test Plan: Project pages have "Developer > View Hovercard" button. Or hover over a project handle, I guess. Also test for empty description and with the description field disabled. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15275 Differential Revision: https://we.phorge.it/D25331 --- ...ricatorProjectHovercardEngineExtension.php | 20 +++++++++++++++++ .../view/PhabricatorProjectCardView.php | 22 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/applications/project/engineextension/PhabricatorProjectHovercardEngineExtension.php b/src/applications/project/engineextension/PhabricatorProjectHovercardEngineExtension.php index d2d1f9ab82..ef8964463f 100644 --- a/src/applications/project/engineextension/PhabricatorProjectHovercardEngineExtension.php +++ b/src/applications/project/engineextension/PhabricatorProjectHovercardEngineExtension.php @@ -28,6 +28,26 @@ final class PhabricatorProjectHovercardEngineExtension ->execute(); $projects = mpull($projects, null, 'getPHID'); + $custom_fields = array(); + foreach ($projects as $project) { + $field = PhabricatorCustomField::getObjectField( + $project, + PhabricatorCustomField::ROLE_VIEW, + 'std:project:internal:description'); + if ($field === null) { + // This means the field is disabled, it would always be null. + break; + } + $field + ->setViewer($viewer) + ->readValueFromObject($project); + $custom_fields[] = $field; + } + + id(new PhabricatorCustomFieldStorageQuery()) + ->addFields($custom_fields) + ->execute(); + return array( 'projects' => $projects, ); diff --git a/src/applications/project/view/PhabricatorProjectCardView.php b/src/applications/project/view/PhabricatorProjectCardView.php index a56697ba7e..03d342b666 100644 --- a/src/applications/project/view/PhabricatorProjectCardView.php +++ b/src/applications/project/view/PhabricatorProjectCardView.php @@ -68,6 +68,28 @@ final class PhabricatorProjectCardView extends AphrontTagView { $description = null; + // This getProxy() feels hacky - see also PhabricatorProjectDatasource:67 + $description_field = PhabricatorCustomField::getObjectField( + $project, + PhabricatorCustomField::ROLE_VIEW, + 'std:project:internal:description'); + + if ($description_field !== null) { + $description_field = $description_field->getProxy(); + + $description = $description_field->getFieldValue(); + if (phutil_nonempty_string($description)) { + $description = PhabricatorMarkupEngine::summarizeSentence($description); + $description = id(new PHUIRemarkupView($viewer, $description)) + ->setContextObject($project); + + $description = phutil_tag( + 'div', + array('class' => 'project-card-body phui-header-shell'), + $description); + } + } + $card = phutil_tag( 'div', array( From b3ac5ceb387fc96e172129e2388080308dcf71f7 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Wed, 5 Jul 2023 09:08:02 +0100 Subject: [PATCH 46/82] Fix DifferentialGetCommitMessageConduitAPIMethod execute strlen(null) Summary: When iterating through the fields of a differential commit, the DifferentialGetCommitMessageConduitAPIMethod execute method explicitly allows a value to be either a string or a null. It then calls strlen upon this possibly null value. We could replace the strlen with phutil_nonempty_string, but as the code has already eliminated variable types other than string or null, it is more efficient to explicitly check for null or '' ``` $value === null or $value == '' ``` Fixes T15527 Test Plan: Run ``` arc diff ``` Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15527 Differential Revision: https://we.phorge.it/D25332 --- .../conduit/DifferentialGetCommitMessageConduitAPIMethod.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php index 51225023ff..a4a2ccc85e 100644 --- a/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php +++ b/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php @@ -115,7 +115,7 @@ final class DifferentialGetCommitMessageConduitAPIMethod $is_title = ($field_key == $key_title); - if (!strlen($value)) { + if ($value === null || $value === '') { if ($is_template) { $commit_message[] = $label.': '; } From cae1246359c64b33eccf61b3fd6ddda6a6101418 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Thu, 6 Jul 2023 13:31:00 +0200 Subject: [PATCH 47/82] Dashboard Tabs: render "Move" buttons grayed out more consistently Summary: If you happen to create a Dashboard by retrieving other people's panels, you were probably affected by this visual bug. It seems that you cannot Move things, but you really can (and that is OK). The reason is, to move things in a Parent Panel, you only need edit permission there, and you do not need to also have edit permissions on every Child Panel. Closes T15492 Test Plan: - From user A: - Create two panels - editable by: User A - From user B: - Create a "Tabs Panel" in a Dashboard - Attach the panels from User A (so, editable by, not you) The meaningful "Move" actions should be not disabled anymore. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15492 Differential Revision: https://we.phorge.it/D25308 --- .../dashboard/paneltype/PhabricatorDashboardTabsPanelType.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php b/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php index 831229bab1..9bc84d820e 100644 --- a/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php +++ b/src/applications/dashboard/paneltype/PhabricatorDashboardTabsPanelType.php @@ -181,7 +181,7 @@ final class PhabricatorDashboardTabsPanelType ->setIcon('fa-chevron-left') ->setHref($prev_uri) ->setWorkflow(true) - ->setDisabled(($prev_key === null) || !$can_edit)); + ->setDisabled($prev_key === null)); $dropdown_menu->addAction( id(new PhabricatorActionView()) @@ -189,7 +189,7 @@ final class PhabricatorDashboardTabsPanelType ->setIcon('fa-chevron-right') ->setHref($next_uri) ->setWorkflow(true) - ->setDisabled(($next_key === null) || !$can_edit)); + ->setDisabled($next_key === null)); $dropdown_menu->addAction( id(new PhabricatorActionView()) From 92861cc1f000f3143be2ba8a0523a0422d1db2d3 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Thu, 6 Jul 2023 13:31:20 +0200 Subject: [PATCH 48/82] Dashboard Tabs: fix action "Move Right" Summary: It seems that if you use the "Move Right" action, you can get an unrelated error message about "Move Left": This is already the first tab. It can not move any farther to the left. This happened because there was an incomplete condition. Closes T15493 Test Plan: - visit /dashboard/panel/ and create at least two panels (please, owned by you) - visit a Dashboard, and add a Tabs Panel - take the first Tab: "Move Right" After this change, "Move Right" now always works. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15493 Differential Revision: https://we.phorge.it/D25307 --- .../panel/PhabricatorDashboardPanelTabsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/dashboard/controller/panel/PhabricatorDashboardPanelTabsController.php b/src/applications/dashboard/controller/panel/PhabricatorDashboardPanelTabsController.php index 2b36d3f8a2..193e4580d6 100644 --- a/src/applications/dashboard/controller/panel/PhabricatorDashboardPanelTabsController.php +++ b/src/applications/dashboard/controller/panel/PhabricatorDashboardPanelTabsController.php @@ -327,7 +327,7 @@ final class PhabricatorDashboardPanelTabsController 'This is already the last tab. It can not move any farther to '. 'the right.')) ->addCancelButton($cancel_uri); - } else if ((string)head_key($old_config) === $target) { + } else if (!$is_next && (string)head_key($old_config) === $target) { return $this->newDialog() ->setTitle(pht('Impossible!')) ->appendParagraph( From 7bebfa289aa18e3ff043ea3a5b00d178ec6756e1 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Thu, 6 Jul 2023 13:31:42 +0200 Subject: [PATCH 49/82] Diffusion commits: add some edge phrases about Revisions Summary: This change implements some messages that were only present from this class: DifferentialRevisionHasCommitEdgeType.php But not in its inverse class: DiffusionCommitHasRevisionEdgeType.php In short: | Before | After | |-----------|-----------| | {F313282} | {F313281} | Closes T15314 Test Plan: Visit a Diffusion commit and use the sidebar menu "Edit Related Objects" to: - add 1 revision - add 2 revisions - remove 1 revision - remove 2 revisions - add 1 revision, remove 1 revision - add 2 revisions, remove 2 revisions Check that you don't see phrases like "added an edge" anymore. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15314 Differential Revision: https://we.phorge.it/D25306 --- .../DiffusionCommitHasRevisionEdgeType.php | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/applications/diffusion/edge/DiffusionCommitHasRevisionEdgeType.php b/src/applications/diffusion/edge/DiffusionCommitHasRevisionEdgeType.php index ce7a899bda..f59cb8e564 100644 --- a/src/applications/diffusion/edge/DiffusionCommitHasRevisionEdgeType.php +++ b/src/applications/diffusion/edge/DiffusionCommitHasRevisionEdgeType.php @@ -25,4 +25,45 @@ final class DiffusionCommitHasRevisionEdgeType extends PhabricatorEdgeType { 'The source commit is associated with the destination revision.'); } + public function getTransactionAddString( + $actor, + $add_count, + $add_edges) { + + return pht( + '%s added %s revision(s): %s.', + $actor, + $add_count, + $add_edges); + } + + public function getTransactionRemoveString( + $actor, + $rem_count, + $rem_edges) { + + return pht( + '%s removed %s revision(s): %s.', + $actor, + $rem_count, + $rem_edges); + } + + public function getTransactionEditString( + $actor, + $total_count, + $add_count, + $add_edges, + $rem_count, + $rem_edges) { + + return pht( + '%s edited revision(s), added %s: %s; removed %s: %s.', + $actor, + $add_count, + $add_edges, + $rem_count, + $rem_edges); + } + } From fb822ba84999cfadf1ce6b53f3133e0603380273 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 10 Jul 2023 12:09:33 +0200 Subject: [PATCH 50/82] Update Facebook icon on Auth Provider page Summary: Closes T15545 Test Plan: Go to `/auth/config/new/` in browser and look at icons. Reviewers: O1 Blessed Committers, Cigaryno, avivey Reviewed By: O1 Blessed Committers, Cigaryno, avivey Subscribers: avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15545 Differential Revision: https://we.phorge.it/D25342 --- resources/celerity/map.php | 10 +++++----- resources/sprite/login_1x/Facebook.png | Bin 773 -> 746 bytes resources/sprite/login_2x/Facebook.png | Bin 860 -> 822 bytes resources/sprite/manifest/login.json | 2 +- webroot/rsrc/image/sprite-login-X2.png | Bin 29663 -> 29001 bytes webroot/rsrc/image/sprite-login.png | Bin 13623 -> 13399 bytes 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 0f0ee9d3f4..58d7a61a59 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '76ed87e3', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => '8abf4250', + 'core.pkg.css' => 'a4ed0b29', 'core.pkg.js' => '2eeda9e0', 'dark-console.pkg.js' => '187792c2', 'differential.pkg.css' => '525f9a1d', @@ -184,7 +184,7 @@ return array( 'rsrc/css/phui/workboards/phui-workboard.css' => '74fc9d98', 'rsrc/css/phui/workboards/phui-workcard.css' => '62056e3b', 'rsrc/css/phui/workboards/phui-workpanel.css' => 'bc06f022', - 'rsrc/css/sprite-login.css' => '0a370010', + 'rsrc/css/sprite-login.css' => '07052ee0', 'rsrc/css/sprite-tokens.css' => 'f1896dc5', 'rsrc/css/syntax/syntax-default.css' => '055fc231', 'rsrc/externals/d3/d3.min.js' => '9d068042', @@ -342,8 +342,8 @@ return array( 'rsrc/image/phrequent_active.png' => 'de66dc50', 'rsrc/image/phrequent_inactive.png' => '79c61baf', 'rsrc/image/resize.png' => '9cc83373', - 'rsrc/image/sprite-login-X2.png' => 'c1458879', - 'rsrc/image/sprite-login.png' => 'f11dad90', + 'rsrc/image/sprite-login-X2.png' => '02896524', + 'rsrc/image/sprite-login.png' => 'e0508107', 'rsrc/image/sprite-tokens-X2.png' => '21621dd9', 'rsrc/image/sprite-tokens.png' => 'bede2580', 'rsrc/image/texture/card-gradient.png' => 'e6892cb4', @@ -906,7 +906,7 @@ return array( 'project-triggers-css' => 'cd9c8bb9', 'project-view-css' => '2f7caa20', 'setup-issue-css' => '5eed85b2', - 'sprite-login-css' => '0a370010', + 'sprite-login-css' => '07052ee0', 'sprite-tokens-css' => 'f1896dc5', 'syntax-default-css' => '055fc231', 'syntax-highlighting-css' => '548567f6', diff --git a/resources/sprite/login_1x/Facebook.png b/resources/sprite/login_1x/Facebook.png index 8c7201b05e1bec48624135498493b7fbdf77f7bd..397046ffba0f118b4c284b041ac548a730973f75 100644 GIT binary patch literal 746 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s3?yAI>n~$qU{nt932_B-TUY<@?CjjLXV3rt z|79yaNtJ(+EdL|{L&$9VhR;Cpmv8^VNgxBL3$7Rs!=x5!=98CykaYpg2ihoI@d;?P zLd7Sg%1_FbpLD7}=~jO-sQCocWmfmeqVAJr{U;kBYWQT|_}RDZb705kxIQ5Ik}>H^ z=HxHgQ@#|<_|mlK>#U96=56`5@z9S=hkhKn`1AOspI7eux_0mPjr+fEJotV0$seHY zPhb6c21Kv_ym=59qo7?A4v^ zz+loU3GxdD(!h{oV&~-I=H^i}Hjasjjm^r*$<51eZJRUq_MI0mfBg9U=g;52|I(#D zegG=<@pN$vk&t9P$enlDL4@Hz5Omc|rD?~vx*3dMV;K}Y7>i~F z2mZb&B@wI0v@yo(q-Xxtd)paBEgXzZXBvlp*=H z-FF^Gz9U65z5J?Hf8EC0qXrC%d6$=5-D_%K1qmI7f6N;rCi#|X?-T(Ec)I$ztaD0e F0sxVlfu{ff delta 760 zcmVgyT%f7@ ziUFe}Bz!xglj;DmfqQGXeE#1m;mqDe&KDR|F6LmgU6y1y7uFrY9rTjOUwn=p zGkh4l@EC?IK28l2MDJPt5`eRLcbcVu)QNj>tm35(OC~euMK6~V={U)a_7h#`Hr zcIAb-XWfolXg$_$y@n(Pq^=|bk63yF<%H+lGnr{wU8<`+0f#R+UKVi0rWS%Fb z-@HJ94u8~jvemzQk1CIm*Qkscm_z>BL}Mv+{oBtNMlL@oyVV-VEg;ofmUpheP|9)` zsp-fga?Ny@gp6NvMp}cepTOWn$Ix@8Pd-~>NtyZk&Q<&9pgiWJZrl#{`KKmZq!g^- z@WV1Is)$=nvhN(t0!SD08J(Y#%|P8~&QN96esPkEPu8NOI*^&&_#HKXmpSnG?=@o+ zwgMV<$oDYMkONtE)@v9gaR@I{!3;Z?frg^RfQ9}88PKAnOvReUZvGG=Apc-eB4CJ0 q8Umn1zz_jL1kCqwWw%wv|BPQc)XYe6y?zw{0000vV6ukfc|L_0* z|K%z^DOY}$EdK;V5~QQE*M9+ZK}ce>18u}q1`$M)n!EM;?o&UHU;cIL(eLj+|NR4N zw5b1N*YG){^K)p|=ah+Gie`MNoBy?S$=8l$Uni{oHh0Un6??v~-ur#W@gHZd{knGV z_uVId9=-VU{LP=2Z~wme@b}}Ff4_bMP5QrR_RjObaIh;0@(Tt92m>P{7dNkvk+Ge# zi>q5qaYi(nKNh4oxgnT?%jL$K79Q24+7NG-6sLH zFYUs~EC#+?wa9U-9OaqoX1OY38`&AjV>zEAix zck<@lHzoVih5b^(_e9-UF>`KTq`ARI?@TEvlaYZ!8kxM%ROa%>nr*ba6 z!nsKGY=f7eVNg&;LAJbMFz2L&hYE{VPFN7)a%YN%0qgwTc5`duZcdkf|G2uQbxuI* z>z`jz*BeFrUCzYu{r%Bxia9$M^4&Sy!!q$*(}y{}IZ9jR81UR#>)WRBsv(kL{`8b@ zRx_SITR-9W!tLA-ZVK_;ZLMQymb!EJgNxJ~(Bqw_7s3l<;x%AVBNuK8dQm$ED7 z{CxR7=Xb~LSI_xjCnj@0*+u41rYQ zX{t%HSAR$dRW!er(8{~|_LZ=>q=TCd&9J&uGGpS6$6nn$w-qlko@8WYTjILtrybw# x))^0U)K4?&?!25KBWEsE?RoaR1e3YqGwG{4x2P62K3NHhZckS~mvv4FO#o_7qzM23 delta 838 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 Date: Fri, 7 Jul 2023 15:35:32 +0100 Subject: [PATCH 51/82] Fix PHP 8.1 strlen(null) in DiffusionView linkBrowse() Summary: Fix PHP 8.1 strlen(null) in DiffusionView linkBrowse(). Fixes T15542 Test Plan: # Go into a diff (eg https://my.phorge.site/D1234) # Click on the Revision Contents - History tab # Click on a base link (the short git revision ID) Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15542 Differential Revision: https://we.phorge.it/D25340 --- src/applications/diffusion/view/DiffusionView.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/diffusion/view/DiffusionView.php b/src/applications/diffusion/view/DiffusionView.php index 795b47c773..268514ff53 100644 --- a/src/applications/diffusion/view/DiffusionView.php +++ b/src/applications/diffusion/view/DiffusionView.php @@ -71,7 +71,7 @@ abstract class DiffusionView extends AphrontView { $display_name = idx($details, 'name'); unset($details['name']); - if (strlen($display_name)) { + if (phutil_nonempty_string($display_name)) { $display_name = phutil_tag( 'span', array( From 85539ce25559b0a4dcfea54562a31d75ae7b27ad Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Wed, 12 Jul 2023 22:02:30 +0200 Subject: [PATCH 52/82] Blur profile image when user account disabled Summary: Add blur and sepia filter to disabled user profile image. Before this change, the image was just greyed out but still fully recognizable. Closes T15515 Test Plan: * Create an account with a custom profile picture * Disable the account * Go to user profile of the account * Go to a task with activity of that account and hover over the account to open card view Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15515 Differential Revision: https://we.phorge.it/D25322 --- resources/celerity/map.php | 6 +++--- webroot/rsrc/css/phui/phui-icon.css | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 58d7a61a59..0cb4208a04 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '76ed87e3', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => 'a4ed0b29', + 'core.pkg.css' => '0ef1e5d9', 'core.pkg.js' => '2eeda9e0', 'dark-console.pkg.js' => '187792c2', 'differential.pkg.css' => '525f9a1d', @@ -161,7 +161,7 @@ return array( 'rsrc/css/phui/phui-header-view.css' => '36c86a58', 'rsrc/css/phui/phui-hovercard.css' => '6ca90fa0', 'rsrc/css/phui/phui-icon-set-selector.css' => '7aa5f3ec', - 'rsrc/css/phui/phui-icon.css' => '4cbc684a', + 'rsrc/css/phui/phui-icon.css' => '084ac612', 'rsrc/css/phui/phui-image-mask.css' => '62c7f4d2', 'rsrc/css/phui/phui-info-view.css' => 'a10a909b', 'rsrc/css/phui/phui-invisible-character-view.css' => 'c694c4a4', @@ -857,7 +857,7 @@ return array( 'phui-hovercard-list' => 'de4b4919', 'phui-hovercard-view-css' => '6ca90fa0', 'phui-icon-set-selector-css' => '7aa5f3ec', - 'phui-icon-view-css' => '4cbc684a', + 'phui-icon-view-css' => '084ac612', 'phui-image-mask-css' => '62c7f4d2', 'phui-info-view-css' => 'a10a909b', 'phui-inline-comment-view-css' => 'a864426f', diff --git a/webroot/rsrc/css/phui/phui-icon.css b/webroot/rsrc/css/phui/phui-icon.css index 5436bb04b1..21097b9232 100644 --- a/webroot/rsrc/css/phui/phui-icon.css +++ b/webroot/rsrc/css/phui/phui-icon.css @@ -41,8 +41,8 @@ a.phui-icon-view:hover { img.phui-image-disabled { opacity: .8; - -webkit-filter: grayscale(100%); - filter: grayscale(100%); + -webkit-filter: blur(4px) grayscale(100%) sepia(25%); + filter: blur(4px) grayscale(100%) sepia(25%); } .phui-icon-view.bluetext { From f7dd8f579a360e7758e9a07ca933106e9f61dcd1 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Thu, 13 Jul 2023 10:23:49 +0100 Subject: [PATCH 53/82] Fix /dashboard/adjust/remove/ PHP 8.1 strlen(null) errors Summary: /dashboard/adjust/remove/ POST requests fail under PHP 8.1 with strlen(null) errors. This change fixes it. Fixes T15549 Test Plan: View a dashboard which has some panels. Eg https://my.phorge.site/dashboard/view/1/ Click on a 'Manage Panel' dropdown and click on 'Remove Panel' Confirm the panel is removed and no strlen(null) errors are generated. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15549 Differential Revision: https://we.phorge.it/D25345 --- .../dashboard/PhabricatorDashboardAdjustController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/dashboard/controller/dashboard/PhabricatorDashboardAdjustController.php b/src/applications/dashboard/controller/dashboard/PhabricatorDashboardAdjustController.php index 86a3ff5805..fc04b94603 100644 --- a/src/applications/dashboard/controller/dashboard/PhabricatorDashboardAdjustController.php +++ b/src/applications/dashboard/controller/dashboard/PhabricatorDashboardAdjustController.php @@ -42,7 +42,7 @@ final class PhabricatorDashboardAdjustController } $column_key = $request->getStr('columnKey'); - if (strlen($column_key)) { + if (phutil_nonempty_string($column_key)) { $columns = $ref_list->getColumns(); if (!isset($columns[$column_key])) { return new Aphront404Response(); @@ -52,7 +52,7 @@ final class PhabricatorDashboardAdjustController $after_ref = null; $after_key = $request->getStr('afterKey'); - if (strlen($after_key)) { + if (phutil_nonempty_string($after_key)) { $after_ref = $ref_list->getPanelRef($after_key); if (!$after_ref) { return new Aphront404Response(); From 8cbbc9f961079fa44821faf450d450fbae8a7596 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Tue, 4 Jul 2023 15:16:13 +0100 Subject: [PATCH 54/82] Fix strlen(null) in DifferentialChangesetViewController loadCoverage() Summary: DifferentialChangesetViewController loadCoverage() fails under PHP 8.1 when test coverage is provided for some but not all modified files. Update the code to replace strlen() with phutil_nonempty_string(). Fixes T15521 Test Plan: View a diff with test coverage for some but not all files. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15521 Differential Revision: https://we.phorge.it/D25328 --- .../controller/DifferentialChangesetViewController.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/applications/differential/controller/DifferentialChangesetViewController.php b/src/applications/differential/controller/DifferentialChangesetViewController.php index 0e263d013c..c4722e8d37 100644 --- a/src/applications/differential/controller/DifferentialChangesetViewController.php +++ b/src/applications/differential/controller/DifferentialChangesetViewController.php @@ -451,10 +451,9 @@ final class DifferentialChangesetViewController extends DifferentialController { continue; } $coverage_data = idx($test_coverage, $changeset->getFileName()); - if (!strlen($coverage_data)) { - continue; + if (phutil_nonempty_string($coverage_data)) { + $coverage[] = $coverage_data; } - $coverage[] = $coverage_data; } if (!$coverage) { From 682fe971a4a907611a4bc51952acef622509eb5e Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Mon, 17 Jul 2023 12:02:26 +0200 Subject: [PATCH 55/82] Do not crop user avatar image in top bar when no Real Name set Summary: Increase required height for avatar image Patch provided by Stang in https://phabricator.wikimedia.org/T307492 Closes T15552 Test Plan: * Set `/config/edit/user.require-real-name/` to `Make real names optional` * Log in as a user without a real name set * Open the user menu in the top bar and look at the user avatar image Reviewers: O1 Blessed Committers, Cigaryno, avivey Reviewed By: O1 Blessed Committers, Cigaryno, avivey Subscribers: avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15552 Differential Revision: https://we.phorge.it/D25348 --- resources/celerity/map.php | 12 ++++++------ .../rsrc/css/phui/object-item/phui-oi-simple-ui.css | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 0cb4208a04..35001dff29 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '76ed87e3', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => '0ef1e5d9', + 'core.pkg.css' => 'e51a98e2', 'core.pkg.js' => '2eeda9e0', 'dark-console.pkg.js' => '187792c2', 'differential.pkg.css' => '525f9a1d', @@ -134,7 +134,7 @@ return array( 'rsrc/css/phui/object-item/phui-oi-drag-ui.css' => 'da15d3dc', 'rsrc/css/phui/object-item/phui-oi-flush-ui.css' => '490e2e2e', 'rsrc/css/phui/object-item/phui-oi-list-view.css' => '9275ff55', - 'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => '6a30fa46', + 'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => '9b03a61f', 'rsrc/css/phui/phui-action-list.css' => '1b0085b2', 'rsrc/css/phui/phui-action-panel.css' => '6c386cbf', 'rsrc/css/phui/phui-badge.css' => '666e25ad', @@ -871,7 +871,7 @@ return array( 'phui-oi-drag-ui-css' => 'da15d3dc', 'phui-oi-flush-ui-css' => '490e2e2e', 'phui-oi-list-view-css' => '9275ff55', - 'phui-oi-simple-ui-css' => '6a30fa46', + 'phui-oi-simple-ui-css' => '9b03a61f', 'phui-pager-css' => 'd022c7ad', 'phui-pinboard-view-css' => '1f08f5d8', 'phui-policy-section-view-css' => '139fdc64', @@ -1538,9 +1538,6 @@ return array( '6a18c42e' => array( 'javelin-install', ), - '6a30fa46' => array( - 'phui-oi-list-view-css', - ), '6a85bc5a' => array( 'javelin-behavior', 'javelin-dom', @@ -1791,6 +1788,9 @@ return array( 'javelin-install', 'javelin-util', ), + '9b03a61f' => array( + 'phui-oi-list-view-css', + ), '9c01e364' => array( 'javelin-behavior', 'javelin-dom', diff --git a/webroot/rsrc/css/phui/object-item/phui-oi-simple-ui.css b/webroot/rsrc/css/phui/object-item/phui-oi-simple-ui.css index e838f1ce3e..fcf2e7ad1b 100644 --- a/webroot/rsrc/css/phui/object-item/phui-oi-simple-ui.css +++ b/webroot/rsrc/css/phui/object-item/phui-oi-simple-ui.css @@ -4,7 +4,7 @@ */ .phui-oi-list-simple .phui-oi-with-image .phui-oi-frame { - min-height: 26px; + min-height: 36px; } .phui-oi-list-simple .phui-oi-image { From 65e57fe23dd30d4d3a7f31b761de3e73b08911cc Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Mon, 3 Jul 2023 17:39:52 +0100 Subject: [PATCH 56/82] Fix PHP 8.1 PhabricatorEditorURIEngine::newForViewer() trim(NULL) error Summary: Under PHP 8.1, PhabricatorEditorURIEngine::newForViewer() is throwing a trim(NULL) error when trying to view a diff. This is because it tries to apply string operations to a user setting which will be null by default. Fixes T15518 Test Plan: Unit test added - arc unit Or just view a diff. Eg: https://my.phorge.site/D1234 Reviewers: O1 Blessed Committers, valerio.bozzolan, avivey Reviewed By: O1 Blessed Committers, valerio.bozzolan, avivey Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15518 Differential Revision: https://we.phorge.it/D25324 --- .../editor/PhabricatorEditorURIEngine.php | 2 +- .../PhabricatorEditorURIEngineTestCase.php | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/infrastructure/editor/PhabricatorEditorURIEngine.php b/src/infrastructure/editor/PhabricatorEditorURIEngine.php index d4821c4ffd..76c95dead2 100644 --- a/src/infrastructure/editor/PhabricatorEditorURIEngine.php +++ b/src/infrastructure/editor/PhabricatorEditorURIEngine.php @@ -16,7 +16,7 @@ final class PhabricatorEditorURIEngine $pattern = $viewer->getUserSetting(PhabricatorEditorSetting::SETTINGKEY); - if (!strlen(trim($pattern))) { + if ($pattern === null || trim($pattern) === '') { return null; } diff --git a/src/infrastructure/editor/__tests__/PhabricatorEditorURIEngineTestCase.php b/src/infrastructure/editor/__tests__/PhabricatorEditorURIEngineTestCase.php index 43cebff2e6..b6a2b4d8db 100644 --- a/src/infrastructure/editor/__tests__/PhabricatorEditorURIEngineTestCase.php +++ b/src/infrastructure/editor/__tests__/PhabricatorEditorURIEngineTestCase.php @@ -3,6 +3,12 @@ final class PhabricatorEditorURIEngineTestCase extends PhabricatorTestCase { + protected function getPhabricatorTestCaseConfiguration() { + return array( + self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES => true, + ); + } + public function testPatternParsing() { $map = array( '' => array(), @@ -129,4 +135,15 @@ final class PhabricatorEditorURIEngineTestCase } } + public function testNewForViewer() { + $phabricator_user = $this->generateNewTestUser(); + try { + $engine = PhabricatorEditorURIEngine::newForViewer($phabricator_user); + $this->assertTrue(true, 'newForViewer did not throw an error'); + } catch (Throwable $ex) { + $this->assertTrue(false, + 'newForViewer threw an exception:'.$ex->getMessage()); + } + } + } From 8af16246920c5fec42035bdd43a571ca20719f59 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Mon, 17 Jul 2023 11:05:03 +0100 Subject: [PATCH 57/82] Fix passing null to trim() error in DiffusionBrowseTableView render() Summary: When viewing the top level of a diffusion repository, $request->getPath() returns null, which then causes trim() to throw an error. Fix is to update DiffusionRequest getPath() such that it returns '' instead of null, thus fixing it's return type. Fixes T15522 Test Plan: Go to https://my.phorge.site/source/myrepo Reviewers: O1 Blessed Committers, valerio.bozzolan, avivey Reviewed By: O1 Blessed Committers, valerio.bozzolan, avivey Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15522 Differential Revision: https://we.phorge.it/D25329 --- src/applications/diffusion/request/DiffusionRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/diffusion/request/DiffusionRequest.php b/src/applications/diffusion/request/DiffusionRequest.php index 4bcb4d3bc5..c301b89b28 100644 --- a/src/applications/diffusion/request/DiffusionRequest.php +++ b/src/applications/diffusion/request/DiffusionRequest.php @@ -254,7 +254,7 @@ abstract class DiffusionRequest extends Phobject { } public function getPath() { - return $this->path; + return coalesce($this->path, ''); } public function getLine() { From 849e18ccbbea99643f51a8ee300446a42f61b418 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Wed, 5 Jul 2023 15:33:02 +0100 Subject: [PATCH 58/82] Fix PhabricatorRepository generateURI PHP 8.1 strlen(null) errors Summary: When viewing a repository in Diffusion, clicking on a folder (eg https://my.phorge.site/source/myrepo/browse/master/myfolder/) will generate multiple strlen(null) exceptions under PHP 8.1 Fix is to replace all the strlen() calls with phutil_nonempty_string() Fixes T15532 Test Plan: View a folder in a repo in Diffusion. Eg https://my.phorge.site/source/myrepo/browse/master/myfolder/ Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15532 Differential Revision: https://we.phorge.it/D25336 --- .../repository/storage/PhabricatorRepository.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php index eb57b31b57..4a1c923622 100644 --- a/src/applications/repository/storage/PhabricatorRepository.php +++ b/src/applications/repository/storage/PhabricatorRepository.php @@ -779,15 +779,15 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO break; case 'compare': $uri = $this->getPathURI("/{$action}/"); - if (strlen($head)) { + if (phutil_nonempty_scalar($head)) { $query['head'] = $head; - } else if (strlen($raw_commit)) { + } else if (phutil_nonempty_scalar($raw_commit)) { $query['commit'] = $raw_commit; - } else if (strlen($raw_branch)) { + } else if (phutil_nonempty_scalar($raw_branch)) { $query['head'] = $raw_branch; } - if (strlen($against)) { + if (phutil_nonempty_scalar($against)) { $query['against'] = $against; } break; From dbc101ca8ae1f766a099471de0a39337307e87cd Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Mon, 17 Jul 2023 13:02:17 +0100 Subject: [PATCH 59/82] Fix PHP 8.1 substr(null) in People > Activity Logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: When someone tries to log on with invalid credentials, a record is inserted in the phabricator_user.user_log table with action = login-fail. The session value of this record is set to null in this case. When you open the People → Activity Logs screen, you will see an exception because of this. Fixes T15555 Test Plan: Go to https://my.phorge.site/people/logs/ after a login failure and a login success. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15555 Differential Revision: https://we.phorge.it/D25351 --- src/applications/people/view/PhabricatorUserLogView.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/people/view/PhabricatorUserLogView.php b/src/applications/people/view/PhabricatorUserLogView.php index cf728af973..ef4fa6f10c 100644 --- a/src/applications/people/view/PhabricatorUserLogView.php +++ b/src/applications/people/view/PhabricatorUserLogView.php @@ -36,7 +36,7 @@ final class PhabricatorUserLogView extends AphrontView { $rows = array(); foreach ($logs as $log) { - $session = substr($log->getSession(), 0, 6); + $session = substr(coalesce($log->getSession(), ''), 0, 6); $actor_phid = $log->getActorPHID(); $user_phid = $log->getUserPHID(); From 27fa498966222482996a3b1efb0e0b1910e4145e Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Mon, 17 Jul 2023 13:25:32 +0100 Subject: [PATCH 60/82] Fix PHP 8.1 strlen(null) error in PhabricatorFile::newChunkedFile() Summary: Fix PHP 8.1 strlen(null) error in PhabricatorFile::newChunkedFile(). Fixes T15499 Test Plan: Added a unit test which replicated the fault, so you can test simply by 'arc unit' Alternatively, see test in T15499 Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15499 Differential Revision: https://we.phorge.it/D25352 --- src/applications/files/storage/PhabricatorFile.php | 2 +- .../files/storage/__tests__/PhabricatorFileTestCase.php | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php index 44e35c6b72..6782a5a90e 100644 --- a/src/applications/files/storage/PhabricatorFile.php +++ b/src/applications/files/storage/PhabricatorFile.php @@ -287,7 +287,7 @@ final class PhabricatorFile extends PhabricatorFileDAO // NOTE: Once we receive the first chunk, we'll detect its MIME type and // update the parent file if a MIME type hasn't been provided. This matters // for large media files like video. - $mime_type = idx($params, 'mime-type'); + $mime_type = idx($params, 'mime-type', ''); if (!strlen($mime_type)) { $file->setMimeType('application/octet-stream'); } diff --git a/src/applications/files/storage/__tests__/PhabricatorFileTestCase.php b/src/applications/files/storage/__tests__/PhabricatorFileTestCase.php index 21cb2daf11..21ad929c3f 100644 --- a/src/applications/files/storage/__tests__/PhabricatorFileTestCase.php +++ b/src/applications/files/storage/__tests__/PhabricatorFileTestCase.php @@ -532,4 +532,11 @@ final class PhabricatorFileTestCase extends PhabricatorTestCase { $this->assertEqual(array(), $alternate_c); } + public function testNewChunkedFile() { + $engine = new PhabricatorTestStorageEngine(); + $file = PhabricatorFile::newChunkedFile($engine, 10, []); + $this->assertTrue($file instanceof PhabricatorFile, + pht('newChunkedFile returns a PhabricatorFile')); + } + } From cb9fcf18d5c33ebce1ab20d9115967e46f0cc205 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Mon, 17 Jul 2023 14:39:42 +0100 Subject: [PATCH 61/82] Fix PHP 8.1 "strlen(null)" exception trying to stop maintenance mode of Diffusion repo Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Use `isset` instead to check if the argument "start" was passed to the CLI command. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=97e163187418), phorge(head=repoMaintStartHistory, ref.master=1c098c273d06, ref.repoMaintStartHistory=0a4a34143528) #0 PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/repository/management/PhabricatorRepositoryManagementMaintenanceWorkflow.php:45] ``` Closes T15476 Test Plan: After applying this change, executing `./bin/repository maintenance --stop R1` on the CLI shows `Took repository "R1" out of maintenance mode.` as expected, instead of an exception. Reviewers: O1 Blessed Committers, valerio.bozzolan, aklapper, avivey Reviewed By: O1 Blessed Committers, valerio.bozzolan, avivey Subscribers: Sten, avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15476 Differential Revision: https://we.phorge.it/D25296 --- .../PhabricatorRepositoryManagementMaintenanceWorkflow.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementMaintenanceWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementMaintenanceWorkflow.php index 6c2f64b31c..513891c5c6 100644 --- a/src/applications/repository/management/PhabricatorRepositoryManagementMaintenanceWorkflow.php +++ b/src/applications/repository/management/PhabricatorRepositoryManagementMaintenanceWorkflow.php @@ -42,7 +42,7 @@ final class PhabricatorRepositoryManagementMaintenanceWorkflow } $message = $args->getArg('start'); - $is_start = (bool)strlen($message); + $is_start = $message !== null; $is_stop = $args->getArg('stop'); if (!$is_start && !$is_stop) { From 0dfc84e2abef6d14d51de5da63c22a023b8130dd Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Wed, 19 Jul 2023 21:27:06 +0200 Subject: [PATCH 62/82] Ponder Answer Comments: indent textarea as Comments Summary: In a Ponder Answer, when adding a Comment, the textarea indentation was a a little bit unintuitive. After this change, the textarea is aligned as a Comment: | Before | After | |-----------|-----------| | {F286220} | {F286221} | Other changes are welcome but this seems to me a good minimum. I also hope this could help not to confuse the Comment field with the Answer field. Closes T15350 Test Plan: - create a Ponder Question - create an Answer - look at the Comments input field that now should be more nicely indented - the normal Response field is not changed at all - the mobile view is not changed at all - click on "Pin Form On Screen" and it must be as before Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15350 Differential Revision: https://we.phorge.it/D25192 --- resources/celerity/map.php | 4 ++-- webroot/rsrc/css/application/ponder/ponder-view.css | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 35001dff29..29bc9d9eb8 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -100,7 +100,7 @@ return array( 'rsrc/css/application/policy/policy-edit.css' => '8794e2ed', 'rsrc/css/application/policy/policy-transaction-detail.css' => 'c02b8384', 'rsrc/css/application/policy/policy.css' => 'ceb56a08', - 'rsrc/css/application/ponder/ponder-view.css' => '05a09d0a', + 'rsrc/css/application/ponder/ponder-view.css' => 'b04bbaff', 'rsrc/css/application/project/project-card-view.css' => 'c1200da7', 'rsrc/css/application/project/project-triggers.css' => 'cd9c8bb9', 'rsrc/css/application/project/project-view.css' => '2f7caa20', @@ -901,7 +901,7 @@ return array( 'policy-css' => 'ceb56a08', 'policy-edit-css' => '8794e2ed', 'policy-transaction-detail-css' => 'c02b8384', - 'ponder-view-css' => '05a09d0a', + 'ponder-view-css' => 'b04bbaff', 'project-card-view-css' => 'c1200da7', 'project-triggers-css' => 'cd9c8bb9', 'project-view-css' => '2f7caa20', diff --git a/webroot/rsrc/css/application/ponder/ponder-view.css b/webroot/rsrc/css/application/ponder/ponder-view.css index 966fb6a1fb..567d7ae99b 100644 --- a/webroot/rsrc/css/application/ponder/ponder-view.css +++ b/webroot/rsrc/css/application/ponder/ponder-view.css @@ -44,10 +44,17 @@ margin-top: 16px; } +/* Indent comments so that are more related to the answer */ .device-desktop .ponder-answer-view .phui-timeline-view { margin-left: 32px; } +/* Indent input box so that it's more related to answer's comments */ +.device-desktop .ponder-answer-view +.phui-comment-form-view:not(.remarkup-assist-pinned) { + margin-left: 94px; +} + .ponder-answer-view .phui-header-subheader { display: inline; margin-left: 12px; From 0f07c07b3bc3f412e591128780e8e969b7382897 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Sat, 22 Jul 2023 13:52:13 +0200 Subject: [PATCH 63/82] Attach Diff to Revision: fix Repository asked twice Summary: If you manually upload a Diff (patch) from the Differential web interface you can select the Repository. We fix the default value of the Repository field during creation mode, guessing the repo from the potentially already-available diff. Closes T15537 Test Plan: - Create a cute Differential Revision from web - Pick a Repository > Continue - Create a new Revision > Continue At this point you should still have that repository instead of nothing. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: avivey, speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15537 Differential Revision: https://we.phorge.it/D25338 --- .../editor/DifferentialRevisionEditEngine.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/applications/differential/editor/DifferentialRevisionEditEngine.php b/src/applications/differential/editor/DifferentialRevisionEditEngine.php index 995179a864..bd1cee7c26 100644 --- a/src/applications/differential/editor/DifferentialRevisionEditEngine.php +++ b/src/applications/differential/editor/DifferentialRevisionEditEngine.php @@ -189,7 +189,7 @@ final class DifferentialRevisionEditEngine // Don't show the "Author" field when creating a revision using the web // workflow, since it adds more noise than signal to this workflow. - if ($this->getIsCreate()) { + if ($is_create) { $author_field->setIsHidden(true); } @@ -239,6 +239,12 @@ final class DifferentialRevisionEditEngine ->setConduitTypeDescription(pht('New reviewers.')) ->setValue($object->getReviewerPHIDsForEdit()); + // Prefill Repository for example when coming from "Attach To". + $repository_phid = $object->getRepositoryPHID(); + if ($is_create && !$repository_phid && $diff) { + $repository_phid = $diff->getRepositoryPHID(); + } + $fields[] = id(new PhabricatorDatasourceEditField()) ->setKey('repositoryPHID') ->setLabel(pht('Repository')) @@ -248,7 +254,7 @@ final class DifferentialRevisionEditEngine ->setDescription(pht('The repository the revision belongs to.')) ->setConduitDescription(pht('Change the repository for this revision.')) ->setConduitTypeDescription(pht('New repository.')) - ->setSingleValue($object->getRepositoryPHID()); + ->setSingleValue($repository_phid); // This is a little flimsy, but allows "Maniphest Tasks: ..." to continue // working properly in commit messages until we fully sort out T5873. From bf025c5fb491be1d20de1d6ac16ccf32c3c69c2b Mon Sep 17 00:00:00 2001 From: Aviv Eyal Date: Mon, 24 Jul 2023 00:41:16 -0700 Subject: [PATCH 64/82] Aphlict - search for default config in the right place Summary: Fix T15502. Test Plan: Renamed `phorge` dir few times, run `./bin/aphlict status` to see message. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15502 Differential Revision: https://we.phorge.it/D25344 --- .../management/PhabricatorAphlictManagementWorkflow.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/applications/aphlict/management/PhabricatorAphlictManagementWorkflow.php b/src/applications/aphlict/management/PhabricatorAphlictManagementWorkflow.php index 3d1a26c91d..16bdc69bc1 100644 --- a/src/applications/aphlict/management/PhabricatorAphlictManagementWorkflow.php +++ b/src/applications/aphlict/management/PhabricatorAphlictManagementWorkflow.php @@ -30,16 +30,16 @@ abstract class PhabricatorAphlictManagementWorkflow $full_path = Filesystem::resolvePath($config_file); $show_path = $full_path; } else { - $root = dirname(dirname(phutil_get_library_root('phabricator'))); + $root = dirname(phutil_get_library_root('phorge')); $try = array( - 'phabricator/conf/aphlict/aphlict.custom.json', - 'phabricator/conf/aphlict/aphlict.default.json', + 'conf/aphlict/aphlict.custom.json', + 'conf/aphlict/aphlict.default.json', ); foreach ($try as $config) { $full_path = $root.'/'.$config; - $show_path = $config; + $show_path = '/'.$config; if (Filesystem::pathExists($full_path)) { break; } From 1e3c9bdfee76b79389104fe00b5f36ad622d0236 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Tue, 25 Jul 2023 14:12:46 +0200 Subject: [PATCH 65/82] Update Diff: fix dead-end when not yours Summary: Fix "Update Patch" for generic Differential revisions. You can now help a coworker to update their patch, from the web. So, if you visit Diff 111 (not yours) and you click "Update Diff", and you paste a valid diff, you arrive here: https://we.phorge.it/differential/diff/222/?revisionID=111 That page as default was suggesting some Diffs that are yours. Plus, now it shows Diff 111. Omitting the Diff from which the workflow was started made no sense and it's certainly an oversight. Any follow-up change is welcome to modernize the selector using AphrontFormTokenizerControl. Closes T15538 Test Plan: - create a Diff on Differential with user A - click on Update Diff from user B (pasting a valid diff) and Continue Now that patch is selected (and selectable). No dead-end anymore. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: avivey, speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15538 Differential Revision: https://we.phorge.it/D25337 --- .../differential/controller/DifferentialDiffViewController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/applications/differential/controller/DifferentialDiffViewController.php b/src/applications/differential/controller/DifferentialDiffViewController.php index e56eb27d99..ff6623efe3 100644 --- a/src/applications/differential/controller/DifferentialDiffViewController.php +++ b/src/applications/differential/controller/DifferentialDiffViewController.php @@ -197,7 +197,6 @@ final class DifferentialDiffViewController extends DifferentialController { if (empty($revisions[$selected_id])) { $selected = id(new DifferentialRevisionQuery()) ->setViewer($viewer) - ->withAuthors(array($viewer->getPHID())) ->withIDs(array($selected_id)) ->requireCapabilities( array( From 1aa532a4768553d3cdba53858fb86ffea371b933 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Fri, 28 Jul 2023 19:01:44 +0200 Subject: [PATCH 66/82] Workboard Columns: avoid page reload on Edit > Cancel Summary: The rationale for this change is that reloading a page unnecessarily wastes resources that we can save. This includes human resources (time) but also computational resources as well. We probably save a fawn for every 1,000 clicks on that button. A message to Greta Thunberg: now Phorge is with you. This is the involved "Cancel" button, that does not reload the page anymore: {F309894} Closes T15471 Test Plan: Workboard > Column > Edit > Cancel: The popup closes gracefully instead of a page refresh. Also try opening the workflow in another tab (/project/board/1/hide/2/) > Cancel: You turn back to your Workboard just as before. Reviewers: O1 Blessed Committers, Matthew Reviewed By: O1 Blessed Committers, Matthew Subscribers: speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15471 Differential Revision: https://we.phorge.it/D25302 --- .../controller/PhabricatorProjectColumnHideController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/applications/project/controller/PhabricatorProjectColumnHideController.php b/src/applications/project/controller/PhabricatorProjectColumnHideController.php index 254beab78c..09217064e2 100644 --- a/src/applications/project/controller/PhabricatorProjectColumnHideController.php +++ b/src/applications/project/controller/PhabricatorProjectColumnHideController.php @@ -136,7 +136,6 @@ final class PhabricatorProjectColumnHideController ->setWidth(AphrontDialogView::WIDTH_FORM) ->setTitle($title) ->appendChild($body) - ->setDisableWorkflowOnCancel(true) ->addCancelButton($view_uri) ->addSubmitButton($button); From 189a5d60478e097ef4f65c8bcf1704bfd8e5b774 Mon Sep 17 00:00:00 2001 From: c7574226 Date: Fri, 28 Jul 2023 18:22:42 +0100 Subject: [PATCH 67/82] Fix strlen(null) PHP 8.1 error when pushing into a fresh repository Summary: Doing a git push into a fresh repository over https fails with a PHP 8.1 strlen(null) error. This fixes it. Fixes T15569 Test Plan: * Create an empty repository on a PHP 8.1 Phorge instance * Clone it * Add some data * git push Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15569 Differential Revision: https://we.phorge.it/D25361 --- src/applications/diffusion/engine/DiffusionCommitHookEngine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/diffusion/engine/DiffusionCommitHookEngine.php b/src/applications/diffusion/engine/DiffusionCommitHookEngine.php index c172f27466..e4e8fd2293 100644 --- a/src/applications/diffusion/engine/DiffusionCommitHookEngine.php +++ b/src/applications/diffusion/engine/DiffusionCommitHookEngine.php @@ -1133,7 +1133,7 @@ final class DiffusionCommitHookEngine extends Phobject { ->setHookWait(phutil_microseconds_since($hook_start)); $identifier = $this->getRequestIdentifier(); - if (strlen($identifier)) { + if ($identifier !== null && strlen($identifier)) { $event->setRequestIdentifier($identifier); } From fa687b4ba0116593f502ffd3f2bfdadf55859240 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Sat, 29 Jul 2023 12:12:49 +0300 Subject: [PATCH 68/82] Always ellipsize long filename in file upload dialog Summary: Firefox does not ellipsize long filenames after selecting them in the File Upload dialog; Chromium does (for unknown reasons). Could hardcode the "remaining" width for the `` element itself (approx. 340px) based on calculating the CSS widths and margins of all surrounding elements but that is error-prone if CSS for one of those surrounding elements ever changed. Thus instead use `max-width: stretch` for the `` element itself. Per its limited support (see https://caniuse.com/?search=max-width), set also `-moz-available` (https://bugzilla.mozilla.org/show_bug.cgi?id=1495868) and `-webkit-fill-available` (see https://bugs.chromium.org/p/chromium/issues/detail?id=611857) aliases. Closes T15553 Test Plan: * Both in Firefox and in Chromium, go to an existing task, select "File Upload", select a file with a long name. * See that the filename is now correctly ellipsized in Firefox. * See no changes in Chromium. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15553 Differential Revision: https://we.phorge.it/D25347 --- resources/celerity/map.php | 6 +++--- webroot/rsrc/css/phui/phui-form-view.css | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 29bc9d9eb8..17a93021a4 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '76ed87e3', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => 'e51a98e2', + 'core.pkg.css' => '67a5ecf3', 'core.pkg.js' => '2eeda9e0', 'dark-console.pkg.js' => '187792c2', 'differential.pkg.css' => '525f9a1d', @@ -154,7 +154,7 @@ return array( 'rsrc/css/phui/phui-document.css' => '52b748a5', 'rsrc/css/phui/phui-feed-story.css' => 'a0c05029', 'rsrc/css/phui/phui-fontkit.css' => '1ec937e5', - 'rsrc/css/phui/phui-form-view.css' => '7536aef9', + 'rsrc/css/phui/phui-form-view.css' => '57edecb7', 'rsrc/css/phui/phui-form.css' => 'd1adb52c', 'rsrc/css/phui/phui-formation-view.css' => 'd2dec8ed', 'rsrc/css/phui/phui-head-thing.css' => 'd7f293df', @@ -849,7 +849,7 @@ return array( 'phui-font-icon-base-css' => '303c9b87', 'phui-fontkit-css' => '1ec937e5', 'phui-form-css' => 'd1adb52c', - 'phui-form-view-css' => '7536aef9', + 'phui-form-view-css' => '57edecb7', 'phui-formation-view-css' => 'd2dec8ed', 'phui-head-thing-view-css' => 'd7f293df', 'phui-header-view-css' => '36c86a58', diff --git a/webroot/rsrc/css/phui/phui-form-view.css b/webroot/rsrc/css/phui/phui-form-view.css index 47f7d1bb2c..0c5331551e 100644 --- a/webroot/rsrc/css/phui/phui-form-view.css +++ b/webroot/rsrc/css/phui/phui-form-view.css @@ -63,6 +63,11 @@ color:{$greytext} !important; } +.aphront-form-input > input[type="file"] { + max-width: stretch; + max-width: -moz-available; + max-width: -webkit-fill-available; +} .aphront-form-error { width: 18%; From 1802ebd2ccc1d8beb1594d3becb57b69f9c1a1aa Mon Sep 17 00:00:00 2001 From: sten Date: Sat, 29 Jul 2023 12:51:00 +0100 Subject: [PATCH 69/82] Fix PHP 8.1 Diffusion history errors Summary: Fix multiple PHP 8.1 errors when viewing Diffusion history. Fixes T15573 Test Plan: View a diffusion history page. Eg https://my.php81.phorge.site/source/myrepo/history/master/ Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15573 Differential Revision: https://we.phorge.it/D25366 --- .../diffusion/controller/DiffusionHistoryController.php | 9 ++++----- .../diffusion/query/pathid/DiffusionPathIDQuery.php | 3 +++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/applications/diffusion/controller/DiffusionHistoryController.php b/src/applications/diffusion/controller/DiffusionHistoryController.php index fb35d9b6ad..eeb8f13118 100644 --- a/src/applications/diffusion/controller/DiffusionHistoryController.php +++ b/src/applications/diffusion/controller/DiffusionHistoryController.php @@ -50,7 +50,7 @@ final class DiffusionHistoryController extends DiffusionController { // ancestors appropriately, but this would currrently be prohibitively // expensive in the general case. - $show_graph = !strlen($drequest->getPath()); + $show_graph = !phutil_nonempty_string($drequest->getPath()); if ($show_graph) { $history_list ->setParents($history_results['parents']) @@ -98,11 +98,10 @@ final class DiffusionHistoryController extends DiffusionController { $viewer = $this->getViewer(); $repository = $drequest->getRepository(); - $no_path = !strlen($drequest->getPath()); - if ($no_path) { - $header_text = pht('History'); - } else { + if (phutil_nonempty_string($drequest->getPath())) { $header_text = $this->renderPathLinks($drequest, $mode = 'history'); + } else { + $header_text = pht('History'); } $header = id(new PHUIHeaderView()) diff --git a/src/applications/diffusion/query/pathid/DiffusionPathIDQuery.php b/src/applications/diffusion/query/pathid/DiffusionPathIDQuery.php index 7c9e721431..d994410034 100644 --- a/src/applications/diffusion/query/pathid/DiffusionPathIDQuery.php +++ b/src/applications/diffusion/query/pathid/DiffusionPathIDQuery.php @@ -48,6 +48,9 @@ final class DiffusionPathIDQuery extends Phobject { */ public static function normalizePath($path) { + // Ensure we have a string, not a null. + $path = coalesce($path, ''); + // Normalize to single slashes, e.g. "///" => "/". $path = preg_replace('@[/]{2,}@', '/', $path); From 007e7621f2988b3959af780ecd90fc5dedea4f37 Mon Sep 17 00:00:00 2001 From: sten Date: Sat, 29 Jul 2023 12:17:05 +0100 Subject: [PATCH 70/82] Fix HarbormasterBuildUnitMessage PHP 8.1 strlen(null) error Summary: Fix HarbormasterBuildUnitMessage PHP 8.1 strlen(null) error. Fixes T15572 Test Plan: Do an 'arc diff' to a PHP 8.1 Phorge server when doing so will trigger unit tests. Reviewers: O1 Blessed Committers, speck Reviewed By: O1 Blessed Committers, speck Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15572 Differential Revision: https://we.phorge.it/D25365 --- .../harbormaster/storage/build/HarbormasterBuildUnitMessage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php b/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php index f2632153c3..0f373babf1 100644 --- a/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php +++ b/src/applications/harbormaster/storage/build/HarbormasterBuildUnitMessage.php @@ -102,7 +102,7 @@ final class HarbormasterBuildUnitMessage $obj->setDuration((float)idx($dict, 'duration')); $path = idx($dict, 'path'); - if (strlen($path)) { + if ($path !== null && strlen($path)) { $obj->setProperty('path', $path); } From 4cedb928aa2032c92e5ef509a3541b191b9d88f6 Mon Sep 17 00:00:00 2001 From: sten Date: Sat, 29 Jul 2023 17:36:01 +0100 Subject: [PATCH 71/82] Fix arc patch PHP 8.1 strlen(null) error Summary: Fix arc patch PHP 8.1 strlen(null) error. When doing an 'arc patch Dxxxx' against a diff on a PHP 8.1 Phorge server we get a strlen(null) error. Updating the idx call to provide a default empty string resolves it. Providing a default empty string to Fixes T15571 Test Plan: arc patch Dxxxx Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15571 Differential Revision: https://we.phorge.it/D25364 --- .../conduit/controller/PhabricatorConduitAPIController.php | 2 +- .../conduit/DifferentialGetCommitMessageConduitAPIMethod.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/applications/conduit/controller/PhabricatorConduitAPIController.php b/src/applications/conduit/controller/PhabricatorConduitAPIController.php index 208ee81d53..994f282f44 100644 --- a/src/applications/conduit/controller/PhabricatorConduitAPIController.php +++ b/src/applications/conduit/controller/PhabricatorConduitAPIController.php @@ -289,7 +289,7 @@ final class PhabricatorConduitAPIController ); } - $token_string = idx($metadata, 'token'); + $token_string = idx($metadata, 'token', ''); if (strlen($token_string)) { if (strlen($token_string) != 32) { diff --git a/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php b/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php index a4a2ccc85e..7f659ab729 100644 --- a/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php +++ b/src/applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php @@ -56,7 +56,7 @@ final class DifferentialGetCommitMessageConduitAPIMethod // show "Field:" templates for some fields even if they are empty. $edit_mode = $request->getValue('edit'); - $is_any_edit = (bool)strlen($edit_mode); + $is_any_edit = (bool)$edit_mode; $is_create = ($edit_mode == 'create'); $field_list = DifferentialCommitMessageField::newEnabledFields($viewer); From df3ac50cb74215d19238019fc8cfb3bab27533d8 Mon Sep 17 00:00:00 2001 From: Benjamin Kausch Date: Mon, 19 Jun 2023 09:13:25 +0200 Subject: [PATCH 72/82] Implements a more informative hovercard for wiki documents Summary: The current hovercard of a wiki document has no further information except the title. This commit adds object type, project tags, parent documents, last author and last edited time to the card. Preview: {F313614} Preview in a pessimistic case: {F325478} Closes T15433 Test Plan: Edit a wiki document with/without project tags and parent documents and see the hovercard in the feed. Reviewers: O1 Blessed Committers, valerio.bozzolan, avivey, Cigaryno Reviewed By: O1 Blessed Committers, valerio.bozzolan, avivey, Cigaryno Subscribers: avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15433 Differential Revision: https://we.phorge.it/D25303 --- resources/celerity/map.php | 4 +- src/__phutil_library_map__.php | 2 + .../PhrictionHovercardEngineExtension.php | 169 ++++++++++++++++++ webroot/rsrc/css/phui/phui-hovercard.css | 21 +++ 4 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 src/applications/phriction/engineextension/PhrictionHovercardEngineExtension.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 17a93021a4..e31d56d36f 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -159,7 +159,7 @@ return array( 'rsrc/css/phui/phui-formation-view.css' => 'd2dec8ed', 'rsrc/css/phui/phui-head-thing.css' => 'd7f293df', 'rsrc/css/phui/phui-header-view.css' => '36c86a58', - 'rsrc/css/phui/phui-hovercard.css' => '6ca90fa0', + 'rsrc/css/phui/phui-hovercard.css' => '39fd2e14', 'rsrc/css/phui/phui-icon-set-selector.css' => '7aa5f3ec', 'rsrc/css/phui/phui-icon.css' => '084ac612', 'rsrc/css/phui/phui-image-mask.css' => '62c7f4d2', @@ -855,7 +855,7 @@ return array( 'phui-header-view-css' => '36c86a58', 'phui-hovercard' => '6199f752', 'phui-hovercard-list' => 'de4b4919', - 'phui-hovercard-view-css' => '6ca90fa0', + 'phui-hovercard-view-css' => '39fd2e14', 'phui-icon-set-selector-css' => '7aa5f3ec', 'phui-icon-view-css' => '084ac612', 'phui-image-mask-css' => '62c7f4d2', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index ddee83b5f1..804290d0d4 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -5644,6 +5644,7 @@ phutil_register_library_map(array( 'PhrictionEditEngineController' => 'applications/phriction/controller/PhrictionEditEngineController.php', 'PhrictionHistoryConduitAPIMethod' => 'applications/phriction/conduit/PhrictionHistoryConduitAPIMethod.php', 'PhrictionHistoryController' => 'applications/phriction/controller/PhrictionHistoryController.php', + 'PhrictionHovercardEngineExtension' => 'applications/phriction/engineextension/PhrictionHovercardEngineExtension.php', 'PhrictionInfoConduitAPIMethod' => 'applications/phriction/conduit/PhrictionInfoConduitAPIMethod.php', 'PhrictionListController' => 'applications/phriction/controller/PhrictionListController.php', 'PhrictionMarkupPreviewController' => 'applications/phriction/controller/PhrictionMarkupPreviewController.php', @@ -12545,6 +12546,7 @@ phutil_register_library_map(array( 'PhrictionEditEngineController' => 'PhrictionController', 'PhrictionHistoryConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionHistoryController' => 'PhrictionController', + 'PhrictionHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', 'PhrictionInfoConduitAPIMethod' => 'PhrictionConduitAPIMethod', 'PhrictionListController' => 'PhrictionController', 'PhrictionMarkupPreviewController' => 'PhabricatorController', diff --git a/src/applications/phriction/engineextension/PhrictionHovercardEngineExtension.php b/src/applications/phriction/engineextension/PhrictionHovercardEngineExtension.php new file mode 100644 index 0000000000..14e63b9521 --- /dev/null +++ b/src/applications/phriction/engineextension/PhrictionHovercardEngineExtension.php @@ -0,0 +1,169 @@ + $this->getProjectHandlesOfDocuments($objects), + 'ancestors' => $this->getAncestorHandlesOfDocuments($objects), + ); + } + + public function renderHovercard( + PHUIHovercardView $hovercard, + PhabricatorObjectHandle $handle, + $object, + $data) { + + $viewer = $this->getViewer(); + $phid = $object->getPHID(); + + $detail_content = array( + id(new PHUIIconView())->setIcon('fa-book'), + ); + + $ancestor_handles = $data['ancestors'][$phid]; + if ($ancestor_handles) { + foreach ($ancestor_handles as $ancestor_handle) { + $detail_content[] = phutil_tag( + 'a', + array( + 'href' => $ancestor_handle->getUri(), + ), + $ancestor_handle->getName()); + + $detail_content[] = id(new PHUIIconView()) + ->setIcon('fa-angle-right') + ->addClass('phui-crumb-divider'); + } + array_pop($detail_content); + } else { + $detail_content[] = pht('Wiki Document'); + } + + $project_handles = $data['projects'][$phid]; + if ($project_handles) { + $list = id(new PHUIHandleTagListView()) + ->setHandles($project_handles) + ->setSlim(true) + ->setShowHovercards(false); + + $detail_content[] = $list; + } + + $hovercard->setDetail( + phutil_tag( + 'div', + array( + 'class' => 'phui-hovercard-object-type', + ), + $detail_content)); + + $content = $object->getContent(); + + if ($content) { + $hovercard->addField( + pht('Last Author'), + $viewer->renderHandle($content->getAuthorPHID())); + + $hovercard->addField( + pht('Last Edited'), + phabricator_dual_datetime($content->getDateCreated(), $viewer)); + } + } + + private function getProjectHandlesOfDocuments($documents) { + $viewer = $this->getViewer(); + $project_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; + $project_phids = array(); + $project_map = array(); + + $project_edges = id(new PhabricatorEdgeQuery()) + ->withSourcePHIDs(mpull($documents, 'getPHID')) + ->withEdgeTypes(array($project_edge_type)) + ->execute(); + + foreach ($project_edges as $document_phid => $edge_types) { + $document_project_phids = array_keys($edge_types[$project_edge_type]); + + $project_map[$document_phid] = array_reverse($document_project_phids); + foreach ($document_project_phids as $project_phid) { + if (!in_array($project_phid, $project_phids, true)) { + $project_phids[] = $project_phid; + } + } + } + + if ($project_phids) { + $project_handles = $viewer->loadHandles($project_phids); + $project_handles = iterator_to_array($project_handles); + $project_handles = mpull($project_handles, null, 'getPHID'); + + foreach ($project_map as $key => $document_project_phids) { + $project_map[$key] = array_select_keys( + $project_handles, + $document_project_phids); + } + } + + return $project_map; + } + + private function getAncestorHandlesOfDocuments($documents) { + $viewer = $this->getViewer(); + $ancestor_slugs = array(); + $ancestor_map = array(); + + foreach ($documents as $document) { + $document_phid = $document->getPHID(); + $document_ancestor_slugs = PhabricatorSlug::getAncestry( + $document->getSlug()); + + $ancestor_map[$document_phid] = $document_ancestor_slugs; + foreach ($document_ancestor_slugs as $slug) { + if (!in_array($slug, $ancestor_slugs, true)) { + $ancestor_slugs[] = $slug; + } + } + } + + if ($ancestor_slugs) { + $ancestors = id(new PhrictionDocumentQuery()) + ->setViewer($viewer) + ->withSlugs($ancestor_slugs) + ->execute(); + $ancestor_phids = mpull($ancestors, 'getPHID', 'getSlug'); + $ancestor_handles = $viewer->loadHandles($ancestor_phids); + $ancestor_handles = iterator_to_array($ancestor_handles); + $ancestor_handles = mpull($ancestor_handles, null, 'getPHID'); + + foreach ($ancestor_map as $key => $document_ancestor_slugs) { + $document_ancestor_phids = array_select_keys( + $ancestor_phids, + $document_ancestor_slugs); + $ancestor_map[$key] = array_select_keys( + $ancestor_handles, + $document_ancestor_phids); + } + } + + return $ancestor_map; + } + +} diff --git a/webroot/rsrc/css/phui/phui-hovercard.css b/webroot/rsrc/css/phui/phui-hovercard.css index 876b0b6e53..ba8057d08d 100644 --- a/webroot/rsrc/css/phui/phui-hovercard.css +++ b/webroot/rsrc/css/phui/phui-hovercard.css @@ -115,3 +115,24 @@ .hovercard-task-view .phui-oi-disabled.phui-workcard { background-color: #fff; } + +.phui-hovercard-object-type { + font-size: 12px; +} + +.phui-hovercard-object-type .phui-icon-view { + margin-right: 6px; +} + +.phui-hovercard-object-type .phui-crumb-divider { + margin: 0px 6px; +} + +.phui-hovercard-object-type .phabricator-handle-tag-list { + margin-top: 10px; +} + +.phui-hovercard-object-type .phabricator-handle-tag-list-item { + display: inline-block; + margin: 0 4px 2px 0; +} From 840a7fab2bc8844c52c3fb3b09d3e2afc84e7879 Mon Sep 17 00:00:00 2001 From: Valerio Bozzolan Date: Tue, 1 Aug 2023 09:39:18 +0200 Subject: [PATCH 73/82] Hide Archived Panels from Dashboards Summary: In edit mode, Archived Panels are shown differently, with content text in grey and with the usual red tag. In view mode, Archived Panels are just not rendered. This makes it easier to design Dashboards with individual components that can be de-activated and re-activated on the fly. Closes T15366. {F325637} Test Plan: Have a Dashboard somewhere (e.g in your homepage). Visit a Panel (W-ID) and Archive it. See that now the Panel is not shown anymore on the Dashboard. Edit the Dashboard and you see the Panel again as "Archived". Anything around is just normal. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: avivey, speck, tobiaswiese, Matthew, Cigaryno Maniphest Tasks: T15366 Differential Revision: https://we.phorge.it/D25368 --- resources/celerity/map.php | 6 +++--- .../PhabricatorDashboardPanelRenderingEngine.php | 15 +++++++++++++++ .../PhabricatorDashboardRenderingEngine.php | 8 +++++++- .../query/PhabricatorDashboardPanelQuery.php | 7 +++++++ webroot/rsrc/css/phui/phui-list.css | 4 ++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/resources/celerity/map.php b/resources/celerity/map.php index e31d56d36f..3fc6387e77 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '76ed87e3', 'conpherence.pkg.js' => '020aebcf', - 'core.pkg.css' => '67a5ecf3', + 'core.pkg.css' => '1a5169fe', 'core.pkg.js' => '2eeda9e0', 'dark-console.pkg.js' => '187792c2', 'differential.pkg.css' => '525f9a1d', @@ -167,7 +167,7 @@ return array( 'rsrc/css/phui/phui-invisible-character-view.css' => 'c694c4a4', 'rsrc/css/phui/phui-left-right.css' => '68513c34', 'rsrc/css/phui/phui-lightbox.css' => '4ebf22da', - 'rsrc/css/phui/phui-list.css' => '0c04affd', + 'rsrc/css/phui/phui-list.css' => 'ccf73664', 'rsrc/css/phui/phui-object-box.css' => 'fdffed5c', 'rsrc/css/phui/phui-pager.css' => 'd022c7ad', 'rsrc/css/phui/phui-pinboard-view.css' => '1f08f5d8', @@ -864,7 +864,7 @@ return array( 'phui-invisible-character-view-css' => 'c694c4a4', 'phui-left-right-css' => '68513c34', 'phui-lightbox-css' => '4ebf22da', - 'phui-list-view-css' => '0c04affd', + 'phui-list-view-css' => 'ccf73664', 'phui-object-box-css' => 'fdffed5c', 'phui-oi-big-ui-css' => 'fa74cc35', 'phui-oi-color-css' => 'b517bfa0', diff --git a/src/applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php b/src/applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php index 52e8cc70d5..cce6ee768f 100644 --- a/src/applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php +++ b/src/applications/dashboard/engine/PhabricatorDashboardPanelRenderingEngine.php @@ -273,6 +273,11 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject { ->addClass('dashboard-box') ->addSigil('dashboard-panel'); + // Allow to style Archived Panels differently. + if ($panel && $panel->getIsArchived()) { + $box->addClass('dashboard-panel-disabled'); + } + if ($this->getMovable()) { $box->addSigil('panel-movable'); } @@ -302,6 +307,16 @@ final class PhabricatorDashboardPanelRenderingEngine extends Phobject { $header = id(new PHUIHeaderView()) ->setHeader($header_text); $header = $this->addPanelHeaderActions($header); + + // If the Panel is Archived, show in edit mode as such. + if ($panel && $panel->getIsArchived()) { + $header->setSubheader( + id(new PHUITagView()) + ->setType(PHUITagView::TYPE_SHADE) + ->setColor(PHUITagView::COLOR_RED) + ->setIcon('fa-ban') + ->setName(pht('Archived'))); + } break; case self::HEADER_MODE_NORMAL: default: diff --git a/src/applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php b/src/applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php index 9b63fcac55..935e85f8bb 100644 --- a/src/applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php +++ b/src/applications/dashboard/engine/PhabricatorDashboardRenderingEngine.php @@ -71,6 +71,13 @@ final class PhabricatorDashboardRenderingEngine extends Phobject { foreach ($column->getPanelRefs() as $panel_ref) { $panel_phid = $panel_ref->getPanelPHID(); + $panel = idx($panels, $panel_phid); + + // Do not render Archived panels in view mode. + if ($panel && $panel->getIsArchived() && !$is_editable) { + continue; + } + $panel_engine = id(new PhabricatorDashboardPanelRenderingEngine()) ->setViewer($viewer) ->setEnableAsyncRendering(true) @@ -83,7 +90,6 @@ final class PhabricatorDashboardRenderingEngine extends Phobject { ->setMovable(true) ->setPanelHandle($handles[$panel_phid]); - $panel = idx($panels, $panel_phid); if ($panel) { $panel_engine->setPanel($panel); } diff --git a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php index c67b756262..54f627eb00 100644 --- a/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php +++ b/src/applications/dashboard/query/PhabricatorDashboardPanelQuery.php @@ -19,6 +19,13 @@ final class PhabricatorDashboardPanelQuery return $this; } + /** + * Whether to get only the Archived (`true`), only the not + * Archived (`false`) or all (`null`). Default to `null` (no filter). + * + * @param null|bool $archived + * @return self + */ public function withArchived($archived) { $this->archived = $archived; return $this; diff --git a/webroot/rsrc/css/phui/phui-list.css b/webroot/rsrc/css/phui/phui-list.css index dee105f25b..0289c58fff 100644 --- a/webroot/rsrc/css/phui/phui-list.css +++ b/webroot/rsrc/css/phui/phui-list.css @@ -287,6 +287,10 @@ border-bottom: 1px solid {$thinblueborder}; } +.dashboard-panel-disabled { + color: {$lightgreytext}; +} + /* - Info Stack ------------------------------------------------------------ */ .phui-info-view + .phui-list-view { From 9fe2bfebe8d66dd8a71cb1d1752b52671ff75497 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Fri, 4 Aug 2023 17:00:53 +0200 Subject: [PATCH 74/82] Fix PHP 8.1 "strlen(null)" exception adding LDAP authentication Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_string() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=788098096e11), phorge(head=master, ref.master=840a7fab2bc8) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php:430] ``` Closes T15587 Test Plan: Go to `/auth/config/edit/?provider=PhabricatorLDAPAuthProvider` and see that "Add Auth Provider: LDAP" page is rendered. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15587 Differential Revision: https://we.phorge.it/D25372 --- src/applications/auth/provider/PhabricatorLDAPAuthProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php b/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php index 19f8c625d7..36a83f3678 100644 --- a/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php +++ b/src/applications/auth/provider/PhabricatorLDAPAuthProvider.php @@ -427,7 +427,7 @@ final class PhabricatorLDAPAuthProvider extends PhabricatorAuthProvider { } $instruction_text = idx($instructions, $key); - if (strlen($instruction_text)) { + if (phutil_nonempty_string($instruction_text)) { $form->appendRemarkupInstructions($instruction_text); } From 39b576b145ae19a0b728240aa2490116d15ad07b Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Sat, 5 Aug 2023 23:23:05 +0200 Subject: [PATCH 75/82] Add HTML header for Atom/RSS discovery on Phame blog pages Summary: Allow easier discovery and subscribing to Atom feeds of Phame blogs. To be extra cautious, also make sure that the added line is a `PhutilSafeHTML`. Original author: @20after4 Closes T15550 Test Plan: Go to `/phame/blog/view/1/` and check the HTML source code. See an additional `` item with `type="application/atom+xml"` in the `` section. Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, 20after4, Cigaryno Maniphest Tasks: T15550 Differential Revision: https://we.phorge.it/D25346 --- .../controller/blog/PhameBlogViewController.php | 9 +++++++++ src/applications/phame/storage/PhameBlog.php | 9 +++++++++ src/view/page/PhabricatorStandardPageView.php | 16 +++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/applications/phame/controller/blog/PhameBlogViewController.php b/src/applications/phame/controller/blog/PhameBlogViewController.php index 758fe955ad..d8b61d8352 100644 --- a/src/applications/phame/controller/blog/PhameBlogViewController.php +++ b/src/applications/phame/controller/blog/PhameBlogViewController.php @@ -117,6 +117,15 @@ final class PhameBlogViewController extends PhameLiveController { $about, )); + $page->addHeadItem(phutil_tag( + 'link', + array( + 'rel' => 'alternate', + 'type' => 'application/atom+xml', + 'href' => $blog->getFeedURI(), + 'title' => $blog->getName(), + ))); + return $page; } diff --git a/src/applications/phame/storage/PhameBlog.php b/src/applications/phame/storage/PhameBlog.php index 717658ec03..587f5daea3 100644 --- a/src/applications/phame/storage/PhameBlog.php +++ b/src/applications/phame/storage/PhameBlog.php @@ -200,6 +200,15 @@ final class PhameBlog extends PhameDAO return '/phame/blog/manage/'.$this->getID().'/'; } + /** + * Get relative URI of Phame blog feed. + * + * @return string Relative URI of Phame blog feed + */ + public function getFeedURI() { + return '/phame/blog/feed/'.$this->getID().'/'; + } + public function getProfileImageURI() { return $this->getProfileImageFile()->getBestURI(); } diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php index 17ce1db8bb..a81820de3c 100644 --- a/src/view/page/PhabricatorStandardPageView.php +++ b/src/view/page/PhabricatorStandardPageView.php @@ -23,6 +23,7 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView private $crumbs; private $navigation; private $footer; + private $headItems = array(); public function setShowFooter($show_footer) { $this->showFooter = $show_footer; @@ -375,6 +376,18 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView } + /** + * Insert a HTML element into of the page to render. + * Used by PhameBlogViewController. + * + * @param PhutilSafeHTML HTML header to add + */ + public function addHeadItem($html) { + if ($html instanceof PhutilSafeHTML) { + $this->headItems[] = $html; + } + } + protected function getHead() { $monospaced = null; @@ -407,9 +420,10 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView } return hsprintf( - '%s%s%s', + '%s%s%s%s', parent::getHead(), $font_css, + phutil_implode_html('', $this->headItems), $response->renderSingleResource('javelin-magical-init', 'phabricator')); } From 226f3150933dfd735da17f19147e2648a5f54e63 Mon Sep 17 00:00:00 2001 From: Andre Klapper Date: Sat, 5 Aug 2023 23:28:47 +0200 Subject: [PATCH 76/82] Fix PHP 8.1 "strlen(null)" exception creating Blueprint Working Copy Summary: `strlen()` was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts `phutil_nonempty_string()` as a replacement, however use `phutil_nonempty_scalar()` as the value might not necessarily be a string object. Note: this may highlight other absurd input values that might be worth correcting instead of just ignoring. If phutil_nonempty_scalar() throws an exception in your instance, report it to Phorge to evaluate and fix that specific corner case. ``` EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261] arcanist(head=master, ref.master=788098096e11), phorge(head=arcpatch-D25239, ref.master=840a7fab2bc8, ref.arcpatch-D25239=870d62ce0ed9) #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldInt.php:36] ``` Closes T15581 Test Plan: Page `Create Blueprint` at `/drydock/blueprint/edit/form/default/` renders as expected in web browser. Try also creating a custom integer field and put some fuzzy data. https://we.phorge.it/book/phorge/article/custom_fields/ Test these values: - 1 (stays as-is) - 0 (stays as-is) - 123.45 (becomes 123) - a "lizard" (becomes zero) - empty ("") (becomes empty) Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15581 Differential Revision: https://we.phorge.it/D25371 --- .../customfield/standard/PhabricatorStandardCustomFieldInt.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldInt.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldInt.php index e8a5b99e0d..0ea7233768 100644 --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldInt.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldInt.php @@ -33,7 +33,7 @@ final class PhabricatorStandardCustomFieldInt } public function setValueFromStorage($value) { - if (strlen($value)) { + if (phutil_nonempty_scalar($value)) { $value = (int)$value; } else { $value = null; From 2da7594344c92ca998f83d25793123baf2c61668 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 10 Aug 2023 17:36:18 +0200 Subject: [PATCH 77/82] Fix a PHP 8.1/8.2 deprecated call to strlen with a NULL argument Summary: This call was preventing notification servers configuration to be properly initialized. Indeed, strlen() was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts phutil_nonempty_string() as a replacement. Fix T15596 Test Plan: Sign in as an administrator, configure the notification server without filling admin path field, you shouldn't get an invalid configuration error Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15596 Differential Revision: https://we.phorge.it/D25381 --- .../config/PhabricatorNotificationServersConfigType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/notification/config/PhabricatorNotificationServersConfigType.php b/src/applications/notification/config/PhabricatorNotificationServersConfigType.php index f13105a249..8fbac5806c 100644 --- a/src/applications/notification/config/PhabricatorNotificationServersConfigType.php +++ b/src/applications/notification/config/PhabricatorNotificationServersConfigType.php @@ -92,7 +92,7 @@ final class PhabricatorNotificationServersConfigType } $path = idx($spec, 'path'); - if ($type == 'admin' && strlen($path)) { + if ($type == 'admin' && phutil_nonempty_string($path)) { throw $this->newException( pht( 'Notification server configuration describes an invalid host '. From eb2be08f9f0e1656e31f68c2c701bf026c7f5050 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 10 Aug 2023 17:40:31 +0200 Subject: [PATCH 78/82] Fix PHP 8.1/8.2 "strlen(null)" exception in SearchController Summary: strlen() was used in Phabricator to check if a generic value is a non-empty string. This behavior is deprecated since PHP 8.1. Phorge adopts phutil_nonempty_string() as a replacement. EXCEPTION: (RuntimeException) strlen(): Passing null to parameter #1 ($string) of type string is deprecated at [/src/error/PhutilErrorHandler.php:261]; PHP message: arcanist(head=master, ref.master=6e4947b55f09), phorge(head=master, ref.master=7bebfa289aa1); PHP message: #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer) called at [/src/applications/search/controller/PhabricatorSearchController.php:16]; Fix T15595 Test Plan: Search something using the main search bar. It should return something (or not) instead to throwing a RuntimeException. Reviewers: O1 Blessed Committers, valerio.bozzolan Reviewed By: O1 Blessed Committers, valerio.bozzolan Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15595 Differential Revision: https://we.phorge.it/D25380 --- .../search/controller/PhabricatorSearchController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/search/controller/PhabricatorSearchController.php b/src/applications/search/controller/PhabricatorSearchController.php index b3d3ab18fa..336604d228 100644 --- a/src/applications/search/controller/PhabricatorSearchController.php +++ b/src/applications/search/controller/PhabricatorSearchController.php @@ -13,7 +13,7 @@ final class PhabricatorSearchController $viewer = $this->getViewer(); $query = $request->getStr('query'); - if ($request->getStr('jump') != 'no' && strlen($query)) { + if ($request->getStr('jump') != 'no' && phutil_nonempty_string($query)) { $jump_uri = id(new PhabricatorDatasourceEngine()) ->setViewer($viewer) ->newJumpURI($query); From 9c8b9a6bbf048af7a18d027c73b23f874e83bad6 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Fri, 11 Aug 2023 10:37:15 +0100 Subject: [PATCH 79/82] Fix PHP 8.1 trim(null) exception in ./bin/diviner generate Summary: When running './bin/diviner generate' under PHP 8.1, we get a trim(null) exception. Fixes T15548 Test Plan: Run './bin/diviner generate' Reviewers: O1 Blessed Committers, avivey Reviewed By: O1 Blessed Committers, avivey Subscribers: avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15548 Differential Revision: https://we.phorge.it/D25353 --- src/applications/diviner/atom/DivinerAtom.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/applications/diviner/atom/DivinerAtom.php b/src/applications/diviner/atom/DivinerAtom.php index f7f8d2c4ac..93e24d5d03 100644 --- a/src/applications/diviner/atom/DivinerAtom.php +++ b/src/applications/diviner/atom/DivinerAtom.php @@ -346,7 +346,7 @@ final class DivinerAtom extends Phobject { ->setContext(idx($dictionary, 'context')) ->setLanguage(idx($dictionary, 'language')) ->setParentHash(idx($dictionary, 'parentHash')) - ->setDocblockRaw(idx($dictionary, 'docblockRaw')) + ->setDocblockRaw(coalesce(idx($dictionary, 'docblockRaw'), '')) ->setProperties(idx($dictionary, 'properties')); foreach (idx($dictionary, 'warnings', array()) as $warning) { From 4b3c384856daa30aaf0f6e9439ea5c5363995c52 Mon Sep 17 00:00:00 2001 From: Steve Campbell Date: Fri, 11 Aug 2023 10:38:08 +0100 Subject: [PATCH 80/82] Fix DifferentialCommitMessageField renderFieldValue PHP 8.1 strlen(null) error Summary: arc diff throws strlen(null) error from DifferentialCommitMessageField renderFieldValue when calling a Phorge server running PHP 8.1 Add unit test, which required a new DifferentialTestCommitMessageField class so as to be able to test the abstract DifferentialCommitMessageField class methods. Fixes T15530 Test Plan: Make a change in a git repo with remote a Phorge server running PHP 8.1 Run: ``` arc diff ``` See exception thrown as per T15530 Reviewers: O1 Blessed Committers, valerio.bozzolan, avivey Reviewed By: O1 Blessed Committers, valerio.bozzolan, avivey Subscribers: speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15530 Differential Revision: https://we.phorge.it/D25334 --- src/__phutil_library_map__.php | 2 ++ .../field/DifferentialCommitMessageField.php | 2 +- ...DifferentialRevisionIDCommitMessageField.php | 2 +- .../DifferentialTestCommitMessageField.php | 10 ++++++++++ .../DifferentialCommitMessageFieldTestCase.php | 17 +++++++++++++++++ 5 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 src/applications/differential/field/DifferentialTestCommitMessageField.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 804290d0d4..615985beaa 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -714,6 +714,7 @@ phutil_register_library_map(array( 'DifferentialTabReplacementTestCase' => 'applications/differential/parser/__tests__/DifferentialTabReplacementTestCase.php', 'DifferentialTagsCommitMessageField' => 'applications/differential/field/DifferentialTagsCommitMessageField.php', 'DifferentialTasksCommitMessageField' => 'applications/differential/field/DifferentialTasksCommitMessageField.php', + 'DifferentialTestCommitMessageField' => 'applications/differential/field/DifferentialTestCommitMessageField.php', 'DifferentialTestPlanCommitMessageField' => 'applications/differential/field/DifferentialTestPlanCommitMessageField.php', 'DifferentialTestPlanField' => 'applications/differential/customfield/DifferentialTestPlanField.php', 'DifferentialTitleCommitMessageField' => 'applications/differential/field/DifferentialTitleCommitMessageField.php', @@ -6760,6 +6761,7 @@ phutil_register_library_map(array( 'DifferentialTabReplacementTestCase' => 'PhabricatorTestCase', 'DifferentialTagsCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTasksCommitMessageField' => 'DifferentialCommitMessageField', + 'DifferentialTestCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTestPlanCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTestPlanField' => 'DifferentialCoreCustomField', 'DifferentialTitleCommitMessageField' => 'DifferentialCommitMessageField', diff --git a/src/applications/differential/field/DifferentialCommitMessageField.php b/src/applications/differential/field/DifferentialCommitMessageField.php index ebe10bcf88..55c5ce0dad 100644 --- a/src/applications/differential/field/DifferentialCommitMessageField.php +++ b/src/applications/differential/field/DifferentialCommitMessageField.php @@ -60,7 +60,7 @@ abstract class DifferentialCommitMessageField } public function renderFieldValue($value) { - if (!strlen($value)) { + if (!phutil_nonempty_string($value)) { return null; } diff --git a/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php b/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php index ac8ba4ebd4..b39145e9df 100644 --- a/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php +++ b/src/applications/differential/field/DifferentialRevisionIDCommitMessageField.php @@ -72,7 +72,7 @@ final class DifferentialRevisionIDCommitMessageField } public function renderFieldValue($value) { - if (!strlen($value)) { + if (!phutil_nonempty_string($value)) { return null; } diff --git a/src/applications/differential/field/DifferentialTestCommitMessageField.php b/src/applications/differential/field/DifferentialTestCommitMessageField.php new file mode 100644 index 0000000000..9d398bc4fd --- /dev/null +++ b/src/applications/differential/field/DifferentialTestCommitMessageField.php @@ -0,0 +1,10 @@ +assertEqual('foo', $test_object->renderFieldValue('foo'), + 'Normal strings should be rendered unaltered'); + + $this->assertEqual(null, $test_object->renderFieldValue(''), + 'Empty strings should be returned as null'); + + $this->assertEqual(null, $test_object->renderFieldValue(null), + 'null values strings should be returned as null'); + + $test_object = new DifferentialRevisionIDCommitMessageField(); + $expected = 'http://phabricator.example.com/D123'; + $this->assertEqual($expected, $test_object->renderFieldValue('123')); + $this->assertEqual(null, $test_object->renderFieldValue(null)); + } + } From 8310591523f59150184f2ab7bfc271325628b28e Mon Sep 17 00:00:00 2001 From: sten Date: Fri, 11 Aug 2023 10:39:59 +0100 Subject: [PATCH 81/82] Fix DifferentialDiff getFieldValuesForConduit PHP 8.1 strlen(null) errors Summary: Fix DifferentialDiff getFieldValuesForConduit PHP 8.1 strlen(null) errors by replacing the strlen() calls with phutil_nonempty_string(). Also needed to update DifferentialDiffTestCase.php to being a PhabricatorTestCase, as it was throwing an exception prior to any code changes - ``` EXCEPTION (Exception): Trying to read configuration "policy.locked" before configuration has been initialized. ``` Fixes T15529 Test Plan: arc diff Reviewers: O1 Blessed Committers, valerio.bozzolan, avivey Reviewed By: O1 Blessed Committers, valerio.bozzolan, avivey Subscribers: avivey, speck, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno Maniphest Tasks: T15529 Differential Revision: https://we.phorge.it/D25333 --- src/__phutil_library_map__.php | 2 +- .../differential/storage/DifferentialDiff.php | 8 ++-- .../__tests__/DifferentialDiffTestCase.php | 38 ++++++++++++++++++- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 615985beaa..83737eea52 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -6565,7 +6565,7 @@ phutil_register_library_map(array( 'DifferentialDiffRepositoryProjectsHeraldField' => 'DifferentialDiffHeraldField', 'DifferentialDiffSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 'DifferentialDiffSearchEngine' => 'PhabricatorApplicationSearchEngine', - 'DifferentialDiffTestCase' => 'PhutilTestCase', + 'DifferentialDiffTestCase' => 'PhabricatorTestCase', 'DifferentialDiffTransaction' => 'PhabricatorApplicationTransaction', 'DifferentialDiffTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'DifferentialDiffViewController' => 'DifferentialController', diff --git a/src/applications/differential/storage/DifferentialDiff.php b/src/applications/differential/storage/DifferentialDiff.php index dfa6d1f791..8f537cff77 100644 --- a/src/applications/differential/storage/DifferentialDiff.php +++ b/src/applications/differential/storage/DifferentialDiff.php @@ -780,7 +780,7 @@ final class DifferentialDiff $refs = array(); $branch = $this->getBranch(); - if (strlen($branch)) { + if (phutil_nonempty_string($branch)) { $refs[] = array( 'type' => 'branch', 'name' => $branch, @@ -788,7 +788,7 @@ final class DifferentialDiff } $onto = $this->loadTargetBranch(); - if (strlen($onto)) { + if (phutil_nonempty_string($onto)) { $refs[] = array( 'type' => 'onto', 'name' => $onto, @@ -796,7 +796,7 @@ final class DifferentialDiff } $base = $this->getSourceControlBaseRevision(); - if (strlen($base)) { + if ($base !== null && strlen($base)) { $refs[] = array( 'type' => 'base', 'identifier' => $base, @@ -804,7 +804,7 @@ final class DifferentialDiff } $bookmark = $this->getBookmark(); - if (strlen($bookmark)) { + if (phutil_nonempty_string($bookmark)) { $refs[] = array( 'type' => 'bookmark', 'name' => $bookmark, diff --git a/src/applications/differential/storage/__tests__/DifferentialDiffTestCase.php b/src/applications/differential/storage/__tests__/DifferentialDiffTestCase.php index 45547aed42..6959b33e27 100644 --- a/src/applications/differential/storage/__tests__/DifferentialDiffTestCase.php +++ b/src/applications/differential/storage/__tests__/DifferentialDiffTestCase.php @@ -1,6 +1,12 @@ true, + ); + } public function testDetectCopiedCode() { $copies = $this->detectCopiesIn('lint_engine.diff'); @@ -73,5 +79,35 @@ EODIFF; $this->assertTrue(true); } + public function testGetFieldValuesForConduit() { + + $parser = new ArcanistDiffParser(); + $raw_diff = <<parseDiff($raw_diff)); + $this->assertTrue(true); + + $field_values = $diff->getFieldValuesForConduit(); + $this->assertTrue(is_array($field_values)); + foreach (['revisionPHID', 'authorPHID', 'repositoryPHID', 'refs'] + as $key) { + $this->assertTrue(array_key_exists($key, $field_values)); + } + + } } From 56789a2fa68167b4af49c1b1e0a502f49caeb126 Mon Sep 17 00:00:00 2001 From: Aviv Eyal Date: Fri, 11 Aug 2023 11:27:50 -0700 Subject: [PATCH 82/82] Replace dedicated Commit Field with an existing one fix T15600 --- src/__phutil_library_map__.php | 2 -- .../field/DifferentialTestCommitMessageField.php | 10 ---------- .../DifferentialCommitMessageFieldTestCase.php | 2 +- 3 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 src/applications/differential/field/DifferentialTestCommitMessageField.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 83737eea52..213b6cf6b1 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -714,7 +714,6 @@ phutil_register_library_map(array( 'DifferentialTabReplacementTestCase' => 'applications/differential/parser/__tests__/DifferentialTabReplacementTestCase.php', 'DifferentialTagsCommitMessageField' => 'applications/differential/field/DifferentialTagsCommitMessageField.php', 'DifferentialTasksCommitMessageField' => 'applications/differential/field/DifferentialTasksCommitMessageField.php', - 'DifferentialTestCommitMessageField' => 'applications/differential/field/DifferentialTestCommitMessageField.php', 'DifferentialTestPlanCommitMessageField' => 'applications/differential/field/DifferentialTestPlanCommitMessageField.php', 'DifferentialTestPlanField' => 'applications/differential/customfield/DifferentialTestPlanField.php', 'DifferentialTitleCommitMessageField' => 'applications/differential/field/DifferentialTitleCommitMessageField.php', @@ -6761,7 +6760,6 @@ phutil_register_library_map(array( 'DifferentialTabReplacementTestCase' => 'PhabricatorTestCase', 'DifferentialTagsCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTasksCommitMessageField' => 'DifferentialCommitMessageField', - 'DifferentialTestCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTestPlanCommitMessageField' => 'DifferentialCommitMessageField', 'DifferentialTestPlanField' => 'DifferentialCoreCustomField', 'DifferentialTitleCommitMessageField' => 'DifferentialCommitMessageField', diff --git a/src/applications/differential/field/DifferentialTestCommitMessageField.php b/src/applications/differential/field/DifferentialTestCommitMessageField.php deleted file mode 100644 index 9d398bc4fd..0000000000 --- a/src/applications/differential/field/DifferentialTestCommitMessageField.php +++ /dev/null @@ -1,10 +0,0 @@ -assertEqual('foo', $test_object->renderFieldValue('foo'), 'Normal strings should be rendered unaltered');