1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-26 07:20:57 +01:00
phorge-phorge/src/infrastructure/util/PhabricatorSlug.php
epriestley 120a7d9164 Improve Phriction page move dialog
Summary:
Fixes T5492. I figured this would be easier to just fix than write a guide for; it actually took me an hour, but I spent like 75% of that futzing with my editor.

  - The Move controller currently accepts either a slug or an ID. I can't find any callsites which pass a slug, and this doesn't make sense. Pretty sure this was copy/pasted from Edit or something. Only accept IDs.
  - Slightly modernize the Move controller (newDialog(), handleRequest(), $viewer).
  - When the user enters a bad slug, warn them that we're going to fix it for them and let them accept or reject the changes.
  - Don't prefill the edit note (this feels inconsistent/unusual).
  - On the form, label the input "Path" instead of "URI".
  - Show the old path, to help remind the user what the input should look like.
  - When a user tries to do a no-op move, show a more tailored message.
  - When the user tries to do an overwriting move, explain how they can fix it.
  - When normalizing a slug like `/question/???/mark/`, make it normalize to `/question/_/mark`.

Test Plan:
  - Tried to move a document to itself.
  - Tried to overwrite a document.
  - Did a bad-path move, accepted corrected path.
  - Did a good-path move.
  - Did a path move with a weird component like `/???/`.
  - Added and executed unit tests.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T5492

Differential Revision: https://secure.phabricator.com/D10838
2014-11-12 07:04:51 -08:00

86 lines
2.1 KiB
PHP

<?php
final class PhabricatorSlug {
public static function normalize($slug) {
$slug = preg_replace('@/+@', '/', $slug);
$slug = trim($slug, '/');
$slug = phutil_utf8_strtolower($slug);
$slug = preg_replace("@[\\x00-\\x19#%&+=\\\\?<> ]+@", '_', $slug);
$slug = preg_replace('@_+@', '_', $slug);
// Remove leading and trailing underscores from each component, if the
// component has not been reduced to a single underscore. For example, "a?"
// converts to "a", but "??" converts to "_".
$parts = explode('/', $slug);
foreach ($parts as $key => $part) {
if ($part != '_') {
$parts[$key] = trim($part, '_');
}
}
$slug = implode('/', $parts);
// Specifically rewrite these slugs. It's OK to have a slug like "a..b",
// but not a slug which is only "..".
// NOTE: These are explicitly not pht()'d, because they should be stable
// across languages.
$replace = array(
'.' => 'dot',
'..' => 'dotdot',
);
foreach ($replace as $pattern => $replacement) {
$pattern = preg_quote($pattern, '@');
$slug = preg_replace(
'@(^|/)'.$pattern.'(\z|/)@',
'\1'.$replacement.'\2', $slug);
}
return $slug.'/';
}
public static function getDefaultTitle($slug) {
$parts = explode('/', trim($slug, '/'));
$default_title = end($parts);
$default_title = str_replace('_', ' ', $default_title);
$default_title = phutil_utf8_ucwords($default_title);
$default_title = nonempty($default_title, pht('Untitled Document'));
return $default_title;
}
public static function getAncestry($slug) {
$slug = self::normalize($slug);
if ($slug == '/') {
return array();
}
$ancestors = array(
'/',
);
$slug = explode('/', $slug);
array_pop($slug);
array_pop($slug);
$accumulate = '';
foreach ($slug as $part) {
$accumulate .= $part.'/';
$ancestors[] = $accumulate;
}
return $ancestors;
}
public static function getDepth($slug) {
$slug = self::normalize($slug);
if ($slug == '/') {
return 0;
} else {
return substr_count($slug, '/');
}
}
}